期望得分:100+100+100=300

实际得分:70+40+20=130

T1 [SCOI2007]kshort弱化版

Description

  有n个城市和m条单向道路,城市编号为1~n。每条道路连接两个不同的城市,且任意两条道路要么起点不同要么终点不同,因此n和m满足m<=n(n-1)。给定两个城市a和b,可以给a到b的所有简单路(所有城市最多经过一次,包括起点和终点)排序:先按长度从小到大排序,长度相同时按照字典序从小到大排序。你的任务是求出a到b的第k短路。

Input

输入第一行包含五个正整数n, m, k, a, b。以下m行每行三个整数u, v, l,表示从城市u到城市v有一条长度为l的单向道路。100%的数据满足:2<=n<=50, 1<=k<=200

Output

  如果a到b的简单路不足k条,输出No,否则输出第k短路:从城市a开始依次输出每个到达的城市,直到城市b,中间用减号"-"分割。

基本思路:A*跑k短路,二进制压缩判重

考场思路:重载运算符比较字典序

错因:spfa判重数组vis,用了边权数组val

另一种方式:记录所有长度<=第k短长度的路径,取第k条

记录路径的时候,定义vector<结构体>,直接sort

vector是从0开始的!!!!

#include<queue>
#include<cstdio>
#include<cstring>
#include<iostream>
#define N 51
using namespace std;
int n,m,k,a,b,sum;
short front[N],nxt[N*N],to[N*N],tot;
short front2[N],nxt2[N*N],to2[N*N],tot2;
int val[N*N],val2[N*N],dis[N];
queue<int>q;
struct node
{
int num,dis2;
long long go;
short cnt,road[N];
bool operator < (node p) const
{
if(dis2+dis[num]!=p.dis2+dis[p.num]) return dis2+dis[num]>p.dis2+dis[p.num];
for(int i=;i<=min(cnt,p.cnt);i++)
if(road[i]!=p.road[i]) return road[i]>p.road[i];
return cnt>p.cnt;
}
}cur,nt;
priority_queue<node>q2;
bool vis[N];
void read(int &x)
{
x=; char c=getchar();
while(!isdigit(c)) c=getchar();
while(isdigit(c)) { x=x*+c-''; c=getchar(); }
}
void add(int u,int v,int w)
{
to[++tot]=v; nxt[tot]=front[u]; front[u]=tot; val[tot]=w;
to2[++tot2]=u; nxt2[tot2]=front2[v]; front2[v]=tot2; val2[tot2]=w;
}
void spfa()
{
memset(dis,,sizeof(dis));
dis[b]=; vis[b]=true; q.push(b);
int now;
while(!q.empty())
{
now=q.front(); q.pop(); vis[now]=false;
for(int i=front[now];i;i=nxt[i])
if(dis[to[i]]>dis[now]+val[i])
{
dis[to[i]]=dis[now]+val[i];
if(!vis[to[i]])
{
vis[to[i]]=true;
q.push(to[i]);
}
}
}
}
bool have(long long x,int y)
{
if(x&(1LL<<y)) return true;
return false;
}
void solve()
{
if(dis[a]>2e9)
{
printf("No");
return;
}
if(a==b) k++;
cur.cnt=;
cur.dis2=;
cur.go=1LL<<a;
cur.num=cur.road[]=a;
q2.push(cur);
while(!q2.empty())
{
cur=q2.top(); q2.pop();
if(cur.num==b)
{
sum++;
if(sum==k)
{
printf("%d",a);
for(int i=;i<=cur.cnt;i++) printf("-%d",cur.road[i]);
return;
}
}
for(int i=front2[cur.num];i;i=nxt2[i])
if(!have(cur.go,to2[i]))
{
nt.cnt=cur.cnt+;
nt.dis2=cur.dis2+val2[i];
nt.go=cur.go|(1LL<<to2[i]);
nt.num=to2[i];
for(int j=;j<=cur.cnt;j++) nt.road[j]=cur.road[j];
nt.road[nt.cnt]=to2[i];
q2.push(nt);
}
}
printf("No");
}
int main()
{
//freopen("bzoj_1073.in","r",stdin);
//freopen("bzoj_1073.out","w",stdout);
read(n); read(m); read(k); read(a); read(b);
int u,v,w;
while(m--)
{
read(u); read(v); read(w);
add(v,u,w);
}
spfa();
solve();
}
#include<queue>
#include<cstdio>
#include<vector>
#include<cstring>
#include<iostream>
#include<algorithm>
#define N 51
using namespace std;
int n,m,k,a,b,sum;
short front[N],nxt[N*N],to[N*N],tot;
short front2[N],nxt2[N*N],to2[N*N],tot2;
int val[N*N],val2[N*N],dis[N];
queue<int>q;
struct node
{
int num,dis2;
long long go;
short cnt,road[N];
bool operator < (node p) const
{
return dis2+dis[num]>p.dis2+dis[p.num];
}
}cur,nt;
vector<node>ans;
priority_queue<node>q2;
bool vis[N];
void read(int &x)
{
x=; char c=getchar();
while(!isdigit(c)) c=getchar();
while(isdigit(c)) { x=x*+c-''; c=getchar(); }
}
void add(int u,int v,int w)
{
to[++tot]=v; nxt[tot]=front[u]; front[u]=tot; val[tot]=w;
to2[++tot2]=u; nxt2[tot2]=front2[v]; front2[v]=tot2; val2[tot2]=w;
}
void spfa()
{
memset(dis,,sizeof(dis));
dis[b]=; vis[b]=true; q.push(b);
int now;
while(!q.empty())
{
now=q.front(); q.pop(); vis[now]=false;
for(int i=front[now];i;i=nxt[i])
if(dis[to[i]]>dis[now]+val[i])
{
dis[to[i]]=dis[now]+val[i];
if(!vis[to[i]])
{
vis[to[i]]=true;
q.push(to[i]);
}
}
}
}
bool have(long long x,int y)
{
if(x&(1LL<<y)) return true;
return false;
}
bool cmp(node h,node g)
{
if(h.dis2!=g.dis2) return h.dis2<g.dis2;
for(int i=;i<=min(h.cnt,g.cnt);i++)
if(h.road[i]!=g.road[i]) return h.road[i]<g.road[i];
return h.cnt<g.cnt;
}
void solve()
{
if(dis[a]>2e9)
{
printf("No");
return;
}
if(a==b) k++;
cur.cnt=;
cur.dis2=;
cur.go=1LL<<a;
cur.num=cur.road[]=a;
q2.push(cur);
while(!q2.empty())
{
cur=q2.top(); q2.pop();
if(cur.num==b)
{
sum++;
ans.push_back(cur);
if(sum>k && cur.dis2>ans[k-].dis2) break;
}
for(int i=front2[cur.num];i;i=nxt2[i])
if(!have(cur.go,to2[i]))
{
nt.cnt=cur.cnt+;
nt.dis2=cur.dis2+val2[i];
nt.go=cur.go|(1LL<<to2[i]);
nt.num=to2[i];
for(int j=;j<=cur.cnt;j++) nt.road[j]=cur.road[j];
nt.road[nt.cnt]=to2[i];
q2.push(nt);
}
}
if(ans.size()>=k)
{
sort(ans.begin(),ans.end(),cmp);
printf("%d",a);
for(int i=;i<=ans[k-].cnt;i++) printf("-%d",ans[k-].road[i]);
return;
}
printf("No");
}
int main()
{
read(n); read(m); read(k); read(a); read(b);
int u,v,w;
while(m--)
{
read(u); read(v); read(w);
add(v,u,w);
}
spfa();
solve();
}

T2[ZJOI2007]最大半连通子图

Description

  一个有向图G=(V,E)称为半连通的(Semi-Connected),如果满足:?u,v∈V,满足u→v或v→u,即对于图中任意
两点u,v,存在一条u到v的有向路径或者从v到u的有向路径。若G'=(V',E')满足V'?V,E'是E中所有跟V'有关的边,
则称G'是G的一个导出子图。若G'是G的导出子图,且G'半连通,则称G'为G的半连通子图。若G'是G所有半连通子图
中包含节点数最多的,则称G'是G的最大半连通子图。给定一个有向图G,请求出G的最大半连通子图拥有的节点数K
,以及不同的最大半连通子图的数目C。由于C可能比较大,仅要求输出C对X的余数。

Input

  第一行包含两个整数N,M,X。N,M分别表示图G的点数与边数,X的意义如上文所述接下来M行,每行两个正整
数a, b,表示一条有向边(a, b)。图中的每个点将编号为1,2,3…N,保证输入中同一个(a,b)不会出现两次。N ≤1
00000, M ≤1000000;对于100%的数据, X ≤10^8

Output

  应包含两行,第一行包含一个整数K。第二行包含整数C Mod X.

tarjan缩环,然后拓扑排序求最长链

注意缩环之后重新构图会出现重边,在拓扑排序里计算方案数时会多算

所以拓扑排序时判断一下是否被同一节点重复更新

错因:没有想到重边,存边的数组大小与点混淆

#include<cstdio>
#include<iostream>
#include<algorithm>
#define N 100001
#define M 1000001
using namespace std;
int mod,tot,cnt;
int front[N],nxt[M],to[M],from[M];
int front2[N],nxt2[M],to2[M],ru[N];
int dp[N][],maxn,ans;
int dfn[N],low[N],col[N],siz[N],st[N],top;
bool vis[N];
int last[N];
void read(int &x)
{
x=; char c=getchar();
while(!isdigit(c)) c=getchar();
while(isdigit(c)) { x=x*+c-''; c=getchar(); }
}
void add(int u,int v)
{
to[++tot]=v; nxt[tot]=front[u]; front[u]=tot; from[tot]=u;
}
void add2(int u,int v)
{
to2[++tot]=v; nxt2[tot]=front2[u]; front2[u]=tot; ru[v]++;
}
void tarjan(int now)
{
low[now]=dfn[now]=++tot;
st[++top]=now;
vis[now]=true;
for(int i=front[now];i;i=nxt[i])
{
if(!dfn[to[i]])
{
tarjan(to[i]);
low[now]=min(low[now],low[to[i]]);
}
else if(vis[to[i]]) low[now]=min(low[now],dfn[to[i]]);
}
if(low[now]==dfn[now])
{
cnt++;
while(top && st[top]!=now)
{
col[st[top]]=cnt;
vis[st[top]]=false;
top--;
}
col[now]=cnt;
vis[now]=false;
top--;
}
}
void topsort()
{
top=;
for(int i=;i<=cnt;i++)
if(!ru[i])
{
st[++top]=i;
dp[i][]=siz[i];
dp[i][]=;
}
int now;
while(top)
{
now=st[top]; top--;
for(int i=front2[now];i;i=nxt2[i])
{
if(dp[now][]+siz[to2[i]]>dp[to2[i]][])
{
dp[to2[i]][]=dp[now][]+siz[to2[i]];
dp[to2[i]][]=dp[now][];
last[to2[i]]=now;
}
else if(dp[now][]+siz[to2[i]]==dp[to2[i]][])
{
if(last[to2[i]]==now)
{
ru[to2[i]]--;
if(!ru[to2[i]]) st[++top]=to2[i];
continue;
}
last[to2[i]]=now;
dp[to2[i]][]+=dp[now][];
dp[to2[i]][]%=mod;
}
ru[to2[i]]--;
if(!ru[to2[i]]) st[++top]=to2[i];
}
}
}
int main()
{
int n,m;
read(n); read(m); read(mod);
int u,v;
for(int i=;i<=m;i++)
{
read(u); read(v);
add(u,v);
}
tot=;
for(int i=;i<=n;i++)
if(!dfn[i]) tarjan(i);
for(int i=;i<=n;i++) siz[col[i]]++;
tot=;
for(int i=;i<=m;i++)
if(col[from[i]]!=col[to[i]]) add2(col[from[i]],col[to[i]]);
topsort();
for(int i=;i<=cnt;i++) maxn=max(maxn,dp[i][]);
for(int i=;i<=cnt;i++)
if(maxn==dp[i][]) ans+=dp[i][],ans%=mod;
printf("%d\n%d",maxn,ans);
}
?

T3[AHOI2006]上学路线route

Description

可可和卡卡家住合肥市的东郊,每天上学他们都要转车多次才能到达市区西端的学校。直到有一天他们两人参加了学校的信息学奥林匹克竞赛小组才发现每天上学的乘车路线不一定是最优的。 可可:“很可能我们在上学的路途上浪费了大量的时间,让我们写一个程序来计算上学需要的最少时间吧!” 合肥市一共设有N个公交车站,不妨将它们编号为1…N的自然数,并认为可可和卡卡家住在1号汽车站附近,而他们学校在N号汽车站。市内有M条直达汽车路线,执行第i条路线的公交车往返于站点pi和qi之间,从起点到终点需要花费的时间为ti。(1<=i<=M, 1<=pi, qi<=N) 两个人坐在电脑前,根据上面的信息很快就编程算出了最优的乘车方案。然而可可忽然有了一个鬼点子,他想趁卡卡不备,在卡卡的输入数据中删去一些路线,从而让卡卡的程序得出的答案大于实际的最短时间。而对于每一条路线i事实上都有一个代价ci:删去路线的ci越大卡卡就越容易发现这个玩笑,可可想知道什么样的删除方案可以达到他的目的而让被删除的公交车路线ci之和最小。 [任务] 编写一个程序:  从输入文件中读取合肥市公交路线的信息;  计算出实际上可可和卡卡上学需要花费的最少时间;  帮助可可设计一个方案,删除输入信息中的一些公交路线,使得删除后从家到学校需要的最少时间变大,而被删除路线的ci和最小;向输出文件输出答案。

Input

输入文件中第一行有两个正整数N和M,分别表示合肥市公交车站和公交汽车路线的个数。以下M行,每行(第i行,总第(i+1)行)用四个正整数描述第i条路线:pi, qi, ti, ci;具体含义见上文描述。

Output

输出文件最多有两行。 第一行中仅有一个整数,表示从可可和卡卡家到学校需要的最短时间。 第二行输出一个整数C,表示Ci之和
 
思路:找出所有的最短路,重新建图,跑最小割
错因:
确定这条边在最短路上:
正确方法:dis[s,u]+w+dis[v,t]=dis[s,t]
错误方法:从t开始枚举,dis[1,u]+w=dis[1,v],只是计算了1到某个点的最短路
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<queue>
#define N 501
#define M 200001
using namespace std;
int n,m;
int dis[N][N];
int e[M][];
int src,decc;
int tot=,front2[N],to2[M<<],nxt2[M<<],cap[M<<],lev[N],cur[N];
bool vis[N];
queue<int>q;
void read(int &x)
{
x=; char c=getchar();
while(!isdigit(c)) c=getchar();
while(isdigit(c)) { x=x*+c-''; c=getchar(); }
}
void add2(int u,int v,int w)
{
to2[++tot]=v; nxt2[tot]=front2[u]; front2[u]=tot; cap[tot]=w;
to2[++tot]=u; nxt2[tot]=front2[v]; front2[v]=tot; cap[tot]=;
}
void build()
{
for(int k=;k<=n;k++)
for(int i=;i<=n;i++)
for(int j=;j<=n;j++)
if(k!=i && i!=j && k!=j)
dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);
int minn=dis[][n];
printf("%d\n",minn);
for(int i=;i<=m;i++)
{
if(dis[][e[i][]]+e[i][]+dis[e[i][]][n]==minn)
add2(e[i][],e[i][],e[i][]);
if(dis[][e[i][]]+e[i][]+dis[e[i][]][n]==minn)
add2(e[i][],e[i][],e[i][]);
} }
bool spfa2()
{
for(int i=;i<=n;i++) cur[i]=front2[i],lev[i]=-;
while(!q.empty()) q.pop();
lev[]=; q.push();
int now;
while(!q.empty())
{
now=q.front(); q.pop();
for(int i=front2[now];i;i=nxt2[i])
if(lev[to2[i]]==- && cap[i]>)
{
lev[to2[i]]=lev[now]+;
if(to2[i]==n) return true;
q.push(to2[i]);
}
}
return false;
}
int dinic(int now,int flow)
{
if(now==n) return flow;
int delta,rest=;
for(int & i=cur[now];i;i=nxt2[i])
if(lev[to2[i]]>lev[now] && cap[i]>)
{
delta=dinic(to2[i],min(cap[i],flow-rest));
if(delta)
{
cap[i]-=delta; cap[i^]+=delta;
rest+=delta; if(rest==flow) break;
}
}
if(rest!=flow) lev[now]=-;
return rest;
}
int main()
{
read(n); read(m);
int u,v,t,c;
memset(dis,,sizeof(dis));
for(int i=;i<=n;i++) dis[i][i]=;
for(int i=;i<=m;i++)
{
read(u); read(v); read(t); read(c);
e[i][]=u; e[i][]=v; e[i][]=t; e[i][]=c;
dis[u][v]=dis[v][u]=min(dis[u][v],t);
}
build();
int ans=;
while(spfa2())
ans+=dinic(,2e9);
printf("%d",ans);
}

NOIP模拟2的更多相关文章

  1. NOIP模拟赛20161022

    NOIP模拟赛2016-10-22 题目名 东风谷早苗 西行寺幽幽子 琪露诺 上白泽慧音 源文件 robot.cpp/c/pas spring.cpp/c/pas iceroad.cpp/c/pas ...

  2. contesthunter暑假NOIP模拟赛第一场题解

    contesthunter暑假NOIP模拟赛#1题解: 第一题:杯具大派送 水题.枚举A,B的公约数即可. #include <algorithm> #include <cmath& ...

  3. NOIP模拟赛 by hzwer

    2015年10月04日NOIP模拟赛 by hzwer    (这是小奇=> 小奇挖矿2(mining) [题目背景] 小奇飞船的钻头开启了无限耐久+精准采集模式!这次它要将原矿运到泛光之源的矿 ...

  4. 大家AK杯 灰天飞雁NOIP模拟赛题解/数据/标程

    数据 http://files.cnblogs.com/htfy/data.zip 简要题解 桌球碰撞 纯模拟,注意一开始就在袋口和v=0的情况.v和坐标可以是小数.为保险起见最好用extended/ ...

  5. 队爷的讲学计划 CH Round #59 - OrzCC杯NOIP模拟赛day1

    题目:http://ch.ezoj.tk/contest/CH%20Round%20%2359%20-%20OrzCC杯NOIP模拟赛day1/队爷的讲学计划 题解:刚开始理解题意理解了好半天,然后发 ...

  6. 队爷的Au Plan CH Round #59 - OrzCC杯NOIP模拟赛day1

    题目:http://ch.ezoj.tk/contest/CH%20Round%20%2359%20-%20OrzCC杯NOIP模拟赛day1/队爷的Au%20Plan 题解:看了题之后觉得肯定是DP ...

  7. 队爷的新书 CH Round #59 - OrzCC杯NOIP模拟赛day1

    题目:http://ch.ezoj.tk/contest/CH%20Round%20%2359%20-%20OrzCC杯NOIP模拟赛day1/队爷的新书 题解:看到这题就想到了 poetize 的封 ...

  8. CH Round #58 - OrzCC杯noip模拟赛day2

    A:颜色问题 题目:http://ch.ezoj.tk/contest/CH%20Round%20%2358%20-%20OrzCC杯noip模拟赛day2/颜色问题 题解:算一下每个仆人到它的目的地 ...

  9. CH Round #52 - Thinking Bear #1 (NOIP模拟赛)

    A.拆地毯 题目:http://www.contesthunter.org/contest/CH%20Round%20%2352%20-%20Thinking%20Bear%20%231%20(NOI ...

  10. CH Round #49 - Streaming #4 (NOIP模拟赛Day2)

    A.二叉树的的根 题目:http://www.contesthunter.org/contest/CH%20Round%20%2349%20-%20Streaming%20%234%20(NOIP 模 ...

随机推荐

  1. 欢迎来怼-----Beta冲刺贡献分数分配结果

    队名:欢迎来怼 小组成员 队长:田继平 成员:李圆圆,葛美义,王伟东,姜珊,邵朔,阚博文

  2. 浅析GCC下C++多重继承 & 虚拟继承的对象内存布局

    继承是C++作为OOD程序设计语言的三大特征(封装,继承,多态)之一,单一非多态继承是比较好理解的,本文主要讲解GCC环境下的多重继承和虚拟继承的对象内存布局. 一.多重继承 先看几个类的定义: 01 ...

  3. Markdown语法实践

    Markdown语法实践 Markdown基本语法 1.标题 # 一级标题 ## 二级标题 ### 三级标题 eg: 一级标题 二级标题 三级标题 2.链接 标准: [Title](URL) 实例: ...

  4. [Oracle收费标准]

    http://www.oracle.com/us/corporate/pricing/technology-price-list-070617.pdf 1: 数据库 2. 中间件 3. weblogi ...

  5. php面试必知必会常见问题

    1 说出常用的10个数组方法 我觉得数组比较最能体现PHP基础语法的一个数据结构了,下面给大家列一下常用的10个关于操作数组的函数 in_array(判断数组中是否有某个元素) implode(将数组 ...

  6. Mysql中关键词执行顺序

    MySQL的语句执行顺序 MySQL的语句一共分为11步,最先执行的总是FROM操作,最后执行的是LIMIT操作.其中每一个操作都会产生一张虚拟的表,这个虚拟的表作为一个处理的输入,只是这些虚拟的表对 ...

  7. jmeter 安装tps插件

    1.下载  jpgc-graphs-basic-2.0.zip 2.解压并将lib 目录下的 jmeter-plugins-cmn-jmeter-0.4.jar 拷贝到 %JMeter%/lib 目录 ...

  8. SSH管理(重启 停止 运行 安装)centos7

    下面整理经常用到管理SSH服务的命令,方便复制哈. SSH服务状态 systemctl status sshd.service SSH运行命令 service sshd start SSH重启命令 s ...

  9. 第187天:js基础---常见的Bom对象

    BOM(Browser Object Mode)浏览器对象模型,是Javascript的重要组成部分.它提供了一系列对象用于与浏览器窗口进行交互,这些对象通常统称为BOM. 一张图了解一下先 1.wi ...

  10. FZU2127_养鸡场

    题目的意思为要你求出满足三边范围条件且周长为n的三角形的数目. 其实做法是直接枚举最短边,然后就可以知道第二条边的取值范围,同时根据给定的范围缩小范围. 同时根据第二条边的范围推出第三条边的范围,再次 ...