最短路+最小割 BZOJ1266 [AHOI2006]上学路线route

1266: [AHOI2006]上学路线route

Time Limit: 3 Sec  Memory Limit: 162 MB
Submit: 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 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

Sample Output

2
5

HINT

2<=N<=500, 1<=M<=124 750, 1<=ti, ci<=10 000
合肥市的公交网络十分发达,你可以认为任意两个车站间都可以通过直达或转车互相到达,当然如果在你提供的删除方案中,家和学校无法互相到达,那么则认为上学需要的最短为正无穷大:这显然是一个合法的方案。

题目大意:给定一张图,每条边有一个长度和一个花费,要求删掉一些边使1到n的最短路变长,求最小花销

先求出最短路,然后将所有在最短路上的边连到新图中,求最小割即为答案。

一波奇特的代码风格……

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<algorithm>
  5 #include<queue>
  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
",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 }