1266: [AHOI2006]上学路线route
1266: [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之和
Sample Input
6 7
1 2 1 3
2 6 1 5
1 3 1 1
3 4 1 1
4 6 1 1
5 6 1 2
1 5 1 4
1 2 1 3
2 6 1 5
1 3 1 1
3 4 1 1
4 6 1 1
5 6 1 2
1 5 1 4
Sample Output
2
5
5
HINT
2<=N<=500, 1<=M<=124 750, 1<=ti, ci<=10 000
合肥市的公交网络十分发达,你可以认为任意两个车站间都可以通过直达或转车互相到达,当然如果在你提供的删除方案中,家和学校无法互相到达,那么则认为上学需要的最短为正无穷大:这显然是一个合法的方案。
这个提示我并没有发现他有什么用 可能是我太弱了
显然 可可要删除一些边 不让卡卡走最短路(心机)
于是我第一遍就跑A*
找所有最短路 统计切断所有最短路的代价之和 结果只有30分
我真是蠢啊 切断所有最短路的代价和 不就是最小割嘛
把所有最短路分离出来 构成一个新图 跑最大流dinic
1 #include <queue> 2 #include <cstdio> 3 #include <cctype> 4 #include <cstring> 5 6 const int MAXN=510; 7 const int INF=0x3f3f3f3f; 8 9 int n,m; 10 11 int f[MAXN][MAXN],dep[MAXN<<1],cur[MAXN<<1]; 12 13 struct node { 14 int x,y; 15 int val; 16 int fee; 17 }; 18 node e[MAXN*MAXN]; 19 20 struct edge { 21 int to; 22 int val; 23 int next; 24 edge() {} 25 edge(int to,int val,int next):to(to),val(val),next(next){} 26 }; 27 edge Edge[MAXN*MAXN*10]; 28 29 int head[MAXN<<1],tot=1; 30 31 inline void read(int&x) { 32 int f=1;register char c=getchar(); 33 for(x=0;!isdigit(c);c=='-'&&(f=-1),c=getchar()); 34 for(;isdigit(c);x=x*10+c-48,c=getchar()); 35 x=x*f; 36 } 37 38 inline void add(int x,int y,int val) { 39 Edge[++tot]=edge(y,val,head[x]); 40 head[x]=tot; 41 Edge[++tot]=edge(x,0,head[y]); 42 head[y]=tot; 43 } 44 45 inline int min(int a,int b) {return a<b?a:b;} 46 47 inline bool bfs() { 48 std::queue<int> q; 49 for(int i=1;i<=n;++i) cur[i]=head[i],dep[i]=-1; 50 q.push(1);dep[1]=0; 51 while(!q.empty()) { 52 int u=q.front(); 53 q.pop(); 54 for(int i=head[u];i;i=Edge[i].next) { 55 int v=Edge[i].to; 56 if(Edge[i].val&&dep[v]==-1) { 57 dep[v]=dep[u]+1; 58 q.push(v); 59 if(v==n) return true; 60 } 61 } 62 } 63 return false; 64 } 65 66 int dfs(int u,int flow) { 67 if(u==n) return flow; 68 int delat,used=0; 69 for(int&i=cur[u];i;i=Edge[i].next) { 70 int v=Edge[i].to; 71 if(dep[v]==dep[u]+1&&Edge[i].val) { 72 delat=dfs(v,min(Edge[i].val,flow-used)); 73 if(delat) { 74 Edge[i].val-=delat; 75 Edge[i^1].val+=delat; 76 used+=delat; 77 if(used==flow) break; 78 } 79 } 80 } 81 if(used!=flow) dep[u]=-1; 82 return used; 83 } 84 85 inline void dinic() { 86 int ans=0; 87 while(bfs()) ans+=dfs(1,INF); 88 printf("%d\n",ans); 89 return; 90 } 91 92 int hh() { 93 read(n);read(m); 94 memset(f,63,sizeof f); 95 for(int i=1;i<=n;++i) f[i][i]=0; 96 for(int x,y,z,k,i=1;i<=m;++i) { 97 read(e[i].x);read(e[i].y);read(e[i].val);read(e[i].fee); 98 f[e[i].x][e[i].y]=min(e[i].val,f[e[i].x][e[i].y]); 99 f[e[i].y][e[i].x]=f[e[i].x][e[i].y]; 100 } 101 for(int k=1;k<=n;++k) 102 for(int i=1;i<=n;++i) 103 for(int j=1;j<=n;++j) 104 f[i][j]=min(f[i][j],f[i][k]+f[k][j]); 105 printf("%d\n",f[1][n]); 106 for(int i=1;i<=m;++i) { 107 int x=e[i].x,y=e[i].y; 108 if(f[1][x]+e[i].val+f[y][n]==f[1][n]) 109 add(x,y,e[i].fee); 110 if(f[1][y]+e[i].val+f[x][n]==f[1][n]) 111 add(y,x,e[i].fee); 112 } 113 dinic(); 114 return 0; 115 } 116 117 int sb=hh(); 118 int main(int argc,char**argv) {;}
作者:乌鸦坐飞机
出处:http://www.cnblogs.com/whistle13326/
新的风暴已经出现
怎么能够停止不前
穿越时空 竭尽全力
我会来到你身边
微笑面对危险
梦想成真不会遥远
鼓起勇气 坚定向前
奇迹一定会出现