第一场
1005.Path
多年后,杰瑞爱上了一个女孩,他经常走很长时间去看望她。但是,因为他花太多的时间和他的女朋友在一起,汤姆觉得被忽视了,想阻止他去看她。经过对小区的研究,Tom发现小区正好由n栋房屋组成,其中一些房屋与直路相连。去看望他的女朋友,杰瑞需要从他的房子1开始,沿着最短路径,到达n。现在汤姆想要阻碍一些道路,使杰瑞走更长的时间到达女孩的家中,他发现阻塞道路的成本等于它的长度。现在他想知道使杰里走得更长所需的最低总成本。注意,如果Jerry一开始不能到他女朋友家,答案显然是零。而且你不需要保证在堵住了一些边之后,仍然有一条路从杰里的家到他女朋友的家。
Q:用最短的花费使最短路径变成。
A:实际上就是要找到所有可能的最短路径,然后做最小割。首先,求出最短路径,然后遍历边集,找到所有 Dis[v]== Dis[u]+ cost的边,构建一个图G'(用于求最大流的图,记得建回退边)。然后跑最大流得到结果(一个图的最小割等于这个图的最大流)。【代码:侯曜辉】
1 #include<algorithm> 2 #include<iostream> 3 #include<cstring> 4 #include<cstdio> 5 #include<queue> 6 using namespace std; 7 typedef long long LL; 8 const int maxv= 10010; 9 const int maxe= 40010; 10 const LL inf= 0x3f3f3f3f3f3f3f3f; 11 12 struct ENode 13 { 14 int from; 15 int to; 16 LL w; 17 int Next; 18 }; 19 ENode edegs[maxe]; 20 int Head[maxv], tnt; 21 void init() 22 { 23 memset(Head, -1, sizeof(Head)); 24 tnt= -1; 25 } 26 void Add_ENode(int a, int b, LL w) 27 { 28 ++ tnt; 29 edegs[tnt].from= a; 30 edegs[tnt].to= b; 31 edegs[tnt].w= w; 32 edegs[tnt].Next= Head[a]; 33 Head[a]= tnt; 34 } 35 36 LL dis[maxv]; 37 struct cmpx 38 { 39 bool operator() (int &a, int &b) const 40 { 41 return dis[a]- dis[b]> 0; 42 } 43 }; 44 void Dijkstra(int x) 45 { 46 priority_queue<int, vector<int>, cmpx> q; 47 memset(dis, inf, sizeof(dis)); 48 dis[x]= 0; 49 q.push(x); 50 51 while (! q.empty()) 52 { 53 int u= q.top(); 54 q.pop(); 55 56 for (int k= Head[u]; k!= -1; k= edegs[k].Next) 57 { 58 int v= edegs[k].to; 59 if (dis[v]> dis[u]+ edegs[k].w ) 60 { 61 dis[v]= dis[u]+ edegs[k].w; 62 q.push(v); 63 } 64 } 65 } 66 } 67 68 /*建新图,跑最大流*/ 69 ENode edegs1[maxe]; 70 int Head1[maxv], tnt1; 71 void init1() 72 { 73 memset(Head1, -1, sizeof(Head1)); 74 tnt1= -1; 75 } 76 void Add_ENode1(int a, int b,LL w) 77 { 78 ++ tnt1; 79 edegs1[tnt1].from= a; 80 edegs1[tnt1].to= b; 81 edegs1[tnt1].w= w; 82 edegs1[tnt1].Next= Head1[a]; 83 Head1[a]= tnt1; 84 ++ tnt1; 85 edegs1[tnt1].from= b; 86 edegs1[tnt1].to= a; 87 edegs1[tnt1].w= 0; 88 edegs1[tnt1].Next= Head1[b]; 89 Head1[b]= tnt1; 90 } 91 void Dijk2(int n) 92 { 93 init1(); 94 for (int u= 1; u<= n; u ++) 95 { 96 for (int k= Head[u]; k!= -1; k= edegs[k].Next) 97 { 98 int v= edegs[k].to; 99 if (dis[v]== dis[u]+ edegs[k].w ) 100 { 101 Add_ENode1(u, v, edegs[k].w); 102 } 103 } 104 } 105 } 106 int level[maxv]; 107 bool bfs_level (int s, int t) 108 { 109 memset(level, -1, sizeof(level)); //所有点的等级初始化为-1; 110 level[s]= 1; //源点的等级为1; 111 int que[maxv]; //队列que:按序保存已搜索到的点; 112 int iq= 0; 113 que[iq ++]= s; //先将源点s 加入队列; 114 for (int i= 0; i< iq; i ++) 115 { 116 int u= que[i]; //取出队首元素; 117 if (u== t) 118 { 119 /*找到汇点t,返回*/ 120 return true; 121 } 122 for (int k= Head1[u]; k!= -1; k= edegs1[k].Next) 123 { 124 /*遍历,查找到之前未找到的、可抵达的点便加入队列*/ 125 int v= edegs1[k].to; 126 if (-1== level[v]&& edegs1[k].w) 127 { 128 level[v]= level[u]+ 1; //深度 +1; 129 que[iq ++]= v; 130 } 131 } 132 } 133 return false; 134 } 135 LL dfs(int now, LL c_max, int t) 136 { 137 /**DFS 实现多路增广*/ 138 /*now:起点;c_max:从源点s到节点now的最大流量;t:汇点、dfs结束的终点*/ 139 if (now== t) return c_max; //当now== t时,c_max便是要求的最大流; 140 LL ret= 0, f; 141 for (int k= Head1[now]; k!= -1; k= edegs1[k].Next) 142 { 143 if (edegs1[k].w&& level[edegs1[k] .to]== level[now]+ 1) 144 { 145 /**/ 146 f= dfs(edegs1[k].to, min(c_max- ret, edegs1[k].w), t); 147 edegs1[k].w-= f; 148 edegs1[k^1].w+= f; 149 ret+= f; 150 if(ret== c_max) return ret; 151 } 152 } 153 return ret; 154 } 155 LL dinic(int s, int t) 156 { 157 LL ans= 0; 158 while(bfs_level(s, t)) 159 { 160 ans+= dfs(s, inf, t); 161 } 162 return ans; 163 } 164 165 int main() 166 { 167 int t; 168 int n, m; 169 scanf("%d", &t); 170 while (t --) 171 { 172 scanf("%d %d", &n, &m); 173 init(); 174 int a, b; 175 LL w; 176 for (int i= 0; i< m; i ++) 177 { 178 scanf("%d %d %lld", &a, &b, &w); 179 Add_ENode(a, b, w); 180 } 181 int start= 1, endd= n; 182 // scanf("%d %d", &start, &endd); 183 Dijkstra(start); 184 LL ans; 185 if (dis[n]== inf) ans= 0; 186 else 187 { 188 Dijk2(n); 189 // cout << dis[n] << " " << tnt1 << endl; 190 // for (int i= 0; i<= tnt1; i ++) 191 // { 192 // cout << edegs1[i].from << "--->" << edegs1[i].to << "--->" << edegs1[i].w << endl; 193 // } 194 ans= dinic(start, endd); 195 } 196 197 printf("%lld\n", ans); 198 } 199 return 0; 200 }
1002.