bzoj 1266: [AHOI2006]上学路线route

这个题可以先floyd求出最短路

在将包含原图中所有S->T最短路径的子图抽出来求最小割(就是最大流啦)

f[S][i]+f[i][j]+f[j][T] == f[S][T]代表i->j边在要求的这个子图中

  1 #include <cstdio>
  2 #include <iostream>
  3 #include <cstring>
  4 #include <algorithm>
  5 using namespace std;
  6 #define N 508
  7 #define M 124758
  8 #define INF 0x7ffffff
  9 
 10 int n,m,tot1,tot2,head1[N],head2[N],f[N][N],lay[N],que[N],l,r,ans;
 11 bool flag[N],vis[N];
 12 struct edge
 13 {
 14     int next,value,node,dist;    
 15 }e[M*2];
 16 struct bow
 17 {
 18     int next,node,res;
 19 }b[M];
 20 
 21 void add1(int u,int v,int t,int c)
 22 {
 23     e[++tot1].node = v;
 24     e[tot1].next = head1[u];
 25     e[tot1].value = c;
 26     e[tot1].dist = t;
 27     head1[u] = tot1;
 28 }
 29 
 30 void init()
 31 {
 32    scanf("%d%d",&n,&m);
 33    for (int i = 1;i <= n;i++) 
 34        for (int j = 1;j <= n;j++) 
 35            if (i != j) f[i][j] = INF;
 36    for (int i = 1;i <= m;i++)
 37    {
 38        int u,v,t,c;
 39        scanf("%d%d%d%d",&u,&v,&t,&c);
 40        add1(u,v,t,c);
 41        add1(v,u,t,c);
 42        f[u][v] = f[v][u] = min(f[u][v],t);
 43    }
 44 }
 45 
 46 void floyd()
 47 {
 48     for (int k = 1;k <= n;k++)
 49         for (int i = 1;i <= n;i++)
 50             for (int j = 1;j <= n;j++)
 51                 f[i][j] = min(f[i][j],f[i][k]+f[k][j]);
 52 }
 53 
 54 void add2(int u,int v,int c)
 55 {
 56     b[tot2].node = v;
 57     b[tot2].res = c;
 58     b[tot2].next = head2[u];
 59     head2[u] = tot2++;
 60 }
 61 
 62 void rebuild()
 63 {
 64     memset(head2,255,sizeof(head2));
 65     for (int i = 1;i <= n;i++)
 66     {
 67         int c = head1[i];
 68         while (c)
 69         {
 70             if (f[1][i] + e[c].dist + f[e[c].node][n] == f[1][n])
 71             {
 72                 add2(i,e[c].node,e[c].value);
 73                 add2(e[c].node,i,0);
 74             }
 75             c = e[c].next;
 76         }
 77     }
 78 }
 79 
 80 bool build()
 81 {
 82 
 83     memset(vis,0,sizeof(vis));
 84     memset(lay,255,sizeof(lay));
 85     l = 0; r = 1; que[1] = 1; lay[1] = 0;
 86     while (l < r)
 87     {
 88         int u = que[++l];
 89         int c = head2[u];
 90         while (c != -1)
 91         {
 92             if (b[c].res && lay[b[c].node] == -1) 
 93                 lay[b[c].node] = lay[u] + 1,que[++r] = b[c].node;
 94             c = b[c].next;
 95         }
 96     }
 97     if (lay[n] == -1) return false;
 98     return true;
 99 }
100 
101 int find(int u,int low)
102 {
103     if (u == n) return low;
104     int ans = 0;
105     int c = head2[u];
106     while (c != -1 && low)
107     {
108         int tans;
109         if (lay[b[c].node] == lay[u]+1 && (tans = find(b[c].node,min(b[c].res,low))))
110         {
111             b[c].res -= tans;
112             b[c^1].res += tans;
113             ans += tans;
114             low -= tans;
115         }
116         c = b[c].next;
117     }
118     return ans;
119 }
120 
121 void dinic()
122 {
123     while (build())
124     {
125         int tans;
126         while(tans = find(1,INF)) ans += tans;
127     }
128 }
129 
130 int main()
131 {
132     init();
133     floyd();
134     printf("%d
",f[1][n]);
135     rebuild();
136     dinic();
137     printf("%d
",ans);
138     return 0;
139 }
View Code

我这个傻逼一开始数组开小了RE了还傻乎乎地跑去去问葱娘!!真他妈丢死人了!!!

原文地址:https://www.cnblogs.com/wulala979/p/3537034.html