最短路+最小割 BZOJ1266 [AHOI2006]上学路线route
1266: [AHOI2006]上学路线route
Time Limit: 3 Sec Memory Limit: 162 MBSubmit: 2287 Solved: 821
[Submit][Status][Discuss]
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 71 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
25
HINT
2<=N<=500, 1<=M<=124 750, 1<=ti, ci<=10 000
合肥市的公交网络十分发达,你可以认为任意两个车站间都可以通过直达或转车互相到达,当然如果在你提供的删除方案中,家和学校无法互相到达,那么则认为上学需要的最短为正无穷大:这显然是一个合法的方案。
题目大意:给定一张图,每条边有一个长度和一个花费,要求删掉一些边使1到n的最短路变长,求最小花销
先求出最短路,然后将所有在最短路上的边连到新图中,求最小割即为答案。
一波奇特的代码风格……
1 #include2 #include 3 #include 4 #include 5 #include 6 using namespace std; 7 const int N=510; 8 const int M=124800; 9 int n,m,s,t; 10 struct node{ 11 int to,nxt,d,c; 12 }e[M*2];int head[N],cnt; 13 bool vis[N]; 14 int dis1[N],dis2[N],son[N]; 15 queue<int>q; 16 struct pic{ 17 int to,nxt,val; 18 }e2[M*2];int head2[N],cnt2; 19 int lev[N]; 20 void add(int f,int t,int d,int c){ 21 cnt++; 22 e[cnt]=(node){t,head[f],d,c}; 23 head[f]=cnt; 24 } 25 void add2(int f,int t,int v){ 26 e2[cnt2]=(pic){t,head2[f],v}; 27 head2[f]=cnt2;cnt2++; 28 } 29 void spfa1(){ 30 memset(dis1,0x3f3f3f3f,sizeof(dis1)); 31 q.push(n);vis[n]=1;dis1[n]=0; 32 while(!q.empty()){ 33 int u=q.front(); 34 q.pop(); 35 vis[u]=0; 36 for(int i=head[u];i!=-1;i=e[i].nxt){ 37 int v=e[i].to; 38 if(dis1[v]>dis1[u]+e[i].d){ 39 dis1[v]=dis1[u]+e[i].d; 40 if(!vis[v]){ 41 vis[v]=1; 42 q.push(v); 43 } 44 } 45 } 46 } 47 } 48 49 void spfa2(){ 50 memset(dis2,0x3f3f3f3f,sizeof(dis2)); 51 q.push(1);vis[1]=1;dis2[1]=0; 52 while(!q.empty()){ 53 int u=q.front(); 54 q.pop(); 55 vis[u]=0; 56 for(int i=head[u];i!=-1;i=e[i].nxt){ 57 int v=e[i].to; 58 if(dis2[v]>dis2[u]+e[i].d){ 59 dis2[v]=dis2[u]+e[i].d; 60 if(!vis[v]){ 61 vis[v]=1; 62 q.push(v); 63 } 64 } 65 } 66 } 67 } 68 bool build(){ 69 memset(lev,-1,sizeof(lev)); 70 q.push(s);lev[s]=1; 71 while(!q.empty()){ 72 int u=q.front(); 73 q.pop(); 74 for(int i=head2[u];i!=-1;i=e2[i].nxt){ 75 int v=e2[i].to; 76 if(lev[v]==-1&&e2[i].val>0){ 77 lev[v]=lev[u]+1; 78 q.push(v); 79 } 80 } 81 } 82 return lev[t]==-1?0:1; 83 } 84 int dfs(int u,int mf){ 85 if(u==t||!mf) return mf; 86 int ret=0; 87 for(int i=head2[u];i!=-1;i=e2[i].nxt){ 88 int v=e2[i].to; 89 if(e2[i].val>0&&lev[v]==lev[u]+1){ 90 int tmp=dfs(v,min(mf,e2[i].val)); 91 mf-=tmp; 92 ret+=tmp; 93 e2[i].val-=tmp; 94 e2[i^1].val+=tmp; 95 } 96 } 97 return ret; 98 } 99 int dinic(){ 100 int ans=0; 101 while(build()) ans+=dfs(s,0x3f3f3f3f); 102 return ans; 103 } 104 int main(){ 105 memset(head,-1,sizeof(head)); 106 memset(head2,-1,sizeof(head2)); 107 scanf("%d%d",&n,&m); 108 s=1;t=n; 109 int a,b,c,d; 110 for(int i=1;i<=m;++i){ 111 scanf("%d%d%d%d",&a,&b,&c,&d); 112 add(a,b,c,d);add(b,a,c,d); 113 } 114 spfa1(); 115 printf("%d\n",dis1[1]); 116 spfa2(); 117 for(int i=1;i<=n;++i) 118 for(int j=head[i];j!=-1;j=e[j].nxt){ 119 int k=e[j].to; 120 if(dis2[i]+dis1[k]+e[j].d==dis2[n]) 121 add2(i,k,e[j].c),add2(k,i,0); 122 } 123 printf("%d",dinic()); 124 return 0; 125 }