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\n",f[1][n]); 135 rebuild(); 136 dinic(); 137 printf("%d\n",ans); 138 return 0; 139 }
我这个傻逼一开始数组开小了RE了还傻乎乎地跑去去问葱娘!!真他妈丢死人了!!!