acm 常用算法

1 图算法 2 kurXX最小生成树 3 #include <iostream> 4 #include <math.h> 5 #include <algorithm> 6 using namespace std; 7 #define M 501 8 #define LIM 20000000 9 10 struct edg{ 11 int u,v; 12 int w; 13 }all_e[M*M/2]; 14 bool operator < (const edg &a,const edg &b){ 15 return a.w<b.w; 16 } 17 int set[M]; 18 19 inline bool uni(int set[],int a,int b){ 20 int ac=0,a2=a,b2=b,bc=0; 21 while(set[a]!=0) {a=set[a];ac++;} 22 if(a2!=a) set[a2]=a; 23 while(set[b]!=0) {b=set[b];bc++;} 24 if(b2!=b) set[b2]=b; 25 if(a==b) return false; 26 if(ac<bc) set[a]=b; 27 else set[b]=a; 28 return true; 29 } 30 int main(){ 31 int i,j,k,n,m,u,v,t; 32 cin >> t; 33 for(k=0;k<t;k++){ 34 memset(set,0,sizeof(set)); 35 cin >> n; 36 int ei=0; 37 for(i=1;i<=n;i++){ 38 for(j=1;j<=n;j++){ 39 if(t!=0){ 40 edg e; 41 e.u=i;e.v=j; 42 scanf("%d",&e.w); 43 if(i<j) 44 all_e[ei++]=e; 45 } 46 } 47 } 48 sort(&all_e[0],&all_e[ei]); 49 int count=0; 50 int size=ei; 51 int max=0; 52 for(i=0;i<size && count < n-1;i++){ 53 if(uni(set,all_e[i].u,all_e[i].v)){ 54 count++; 55 if(all_e[i].w>all_e[max].w) max=i; 56 } 57 } 58 printf("%d/n",all_e[max].w); 59 } 60 return 0; 61 } 62 Prim 63 #include <iostream> 64 using namespace std; 65 #define M 2001 66 67 int set[M]={0},g[M][M]; 68 char str[M][8]; 69 70 inline void make_map(int n,int g[M][M]){ 71 int i,j,k; 72 for(i=1;i<=n;i++){ 73 for(j=i+1;j<=n;j++){ 74 int c=0; 75 for(k=0;k<7;k++) 76 if(str[i][k]!=str[j][k]) c++; 77 g[i][j]=g[j][i]=c; 78 } 79 } 80 } 81 82 int main(){ 83 int n,q[M],qf=0,ql=0,d[M],u; 84 char c; 85 scanf("%d%c",&n,&c); 86 int i; 87 while(n!=0){ 88 memset(set,0,sizeof(set)); memset(g,0,sizeof(g)); 89 for(i=1;i<=n;i++) { 90 scanf("%s",&str[i]); 91 q[i-1]=i; 92 d[i]=2000000; 93 } 94 qf=0;ql=n-1; 95 make_map(n,g); 96 int sum=0; 97 int f=false; 98 while(qf<=ql){ 99 int min=qf; 100 for(i=qf+1;i<=ql;i++){ 101 if(d[q[i]] < d[q[min]]) min=i; 102 } 103 swap(q[qf],q[min]); 104 u=q[qf]; qf++; 105 if(f) sum+=d[u]; 106 for(i=1;i<=n;i++){ 107 if(g[u][i] !=0 && g[u][i] < d[i]) d[i]=g[u][i]; 108 } 109 f=true; 110 } 111 printf("The highest possible quality is 1/%d./n",sum); 112 scanf("%d%c",&n,&c); 113 } 114 return 0; 115 } 116 堆实现最短路 117 #include <iostream> 118 #include <string> 119 #include <stdlib.h> 120 #include <vector>; 121 using namespace std; 122 #define M 1001 123 #define LIM 2000000000 124 125 struct dd{ //最短距离 126 int w,q;//w是距离值,q是堆中的相对位置 127 }d[M],d2[M]; 128 struct node{ 129 int v,w; 130 }; 131 int h[M],hs; 132 vector<node> g[M],g2[M]; 133 void change_key(dd d[M],int v,int w){ 134 d[v].w=w; 135 int i=d[v].q; 136 while(i>1 && d[h[i/2]].w>d[h[i]].w){ 137 swap(h[i],h[i/2]); 138 swap(d[h[i]].q,d[h[i/2]].q); 139 i=i/2; 140 } 141 } 142 inline void min_heaphy(dd d[M],int *a,int i,int s){//s 为堆大小 143 int l=i*2,r=i*2+1; 144 int miner=i; 145 if (l<=s && d[a[i]].w>d[a[l]].w) 146 miner = l; 147 else miner=i; 148 if (r<=s && d[a[miner]].w>d[a[r]].w) 149 miner=r; 150 if(miner!=i){ 151 swap(a[i],a[miner]); 152 swap(d[a[i]].q,d[a[miner]].q); 153 min_heaphy(d,a,miner,s); 154 } 155 } 156 inline void init(dd d[M],int n,int s){ //初始化图和堆 157 int i; 158 hs=n; 159 for(i=1;i<=n;i++){d[i].w=LIM;h[i]=d[i].q=i;} 160 change_key(d,s,0); 161 } 162 inline void relax(dd d[M],int u,int v,int duv){ 163 if(d[v].w>d[u].w+duv) change_key(d,v,d[u].w+duv); 164 } 165 void dijkstra(vector<node> g[M],dd d[M],int n,int s){ //n is |V| && s is the source 166 init(d,n,s); 167 int i; 168 while(hs!=0){ 169 int u=h[1]; 170 swap(h[1],h[hs]); 171 swap(d[h[1]].q,d[h[hs]].q); 172 hs--; 173 min_heaphy(d,h,1,hs); 174 for(i=0;i<g[u].size();i++) relax(d,u,g[u][i].v,g[u][i].w); 175 } 176 } 177 最短路DIJ普通版 178 #define M 101 179 #define LIM 20000000 180 181 int g[M][M],d[M],fd[2][M][M],gt[M][M],set[M]; 182 inline void init(int d[M],int n,int s){ //初始化图 183 int i; 184 for(i=1;i<=n;i++) d[i]=LIM; 185 d[s]=0; 186 } 187 188 inline void relax(int d[M],int u,int v,int duv){ 189 if(d[v]>d[u]+duv) d[v]=d[u]+duv; 190 } 191 void dijkstra(int g[M][M],int d[M],int n,int s){ //n is |V| && s is the source 192 init(d,n,s); 193 int q[M],ql=1,qf=1; //队列 194 int i; 195 for(i=1;i<=n;i++) q[ql++]=i; 196 while(qf!=ql){ 197 int min=qf; 198 for(i=qf;i<ql;i++) if(d[q[i]]<d[q[min]]) min=i; 199 swap(q[qf],q[min]); //q[qf] is the min 200 int u=q[qf++]; 201 for(i=1;i<=n;i++){ 202 if(g[u][i]!=0) relax(d,u,i,g[u][i]); 203 } 204 } 205 } 206 floyd 207 #include <iostream> 208 #include <vector> 209 using namespace std; 210 #define M 301 211 #define LIM 200000000 212 int w[M][M],d[2][M][M]; 213 214 void floyd(int g[M][M],int d[2][M][M],int n){ 215 int i,j,k; 216 for(i=1;i<=n;i++){ 217 for(j=1;j<=n;j++){ 218 d[0][i][j]=g[i][j]; 219 } 220 d[0][i][i]=0; 221 } //这里是令d[0]=g 222 for(k=1;k<=n;k++){ 223 for(i=1;i<=n;i++) 224 for(j=1;j<=n;j++){ 225 int t1=k%2; int t2=(t1+1)%2; 226 d[t1][i][j]=d[t2][i][j] < d[t2][i][k]+d[t2][k][j]?d[t2][i][j]:d[t2][i][k]+d[t2][k][j]; 227 } 228 } 229 } 230 BELL_MAN 231 inline void init(int d[M],int n,int s){ //初始化图 232 int i; 233 for(i=1;i<=n;i++) d[i]=2000000000; 234 d[s]=0; 235 } 236 237 inline void relax(int d[M],int u,int v,int duv){ 238 if(d[v]>d[u]+duv) d[v]=d[u]+duv; 239 } 240 241 void bell_man(int g[M][M],int d[M],int n,int s){ //n个结点 s为源点 242 int i,j,k; 243 init(d,n,s); 244 for(k=1;k<n;k++){ 245 for(i=1;i<=n;i++) 246 for(j=1;j<=n;j++){ 247 if(g[i][j]!=0) relax(d,i,j,g[i][j]); 248 } 249 } 250 } 251 拓扑排序 252 #include <iostream> 253 #include <stack> 254 #include <vector> 255 #include <list> 256 using namespace std; 257 vector <int> order; 258 void find_id(list<int> g[],int id[],int n){ //寻找入度,没有使用 259 int i; 260 list<int>::iterator k; 261 for(i=0;i<n;i++){ 262 for(k=g[i].begin();k!=g[i].end();k++){ 263 id[*k]++; 264 } 265 } 266 } 267 void topo(list<int> g[],int id[],int n,bool &OK,bool &incon){//OK==false 表示未确定顺序 incon==true 表示发现矛盾 268 stack<int> s; 269 order.erase(order.begin(),order.end()); 270 int t[26]; 271 copy(&id[0],&id[n],&t[0]); 272 int i; 273 for(i=0;i<n;i++){ 274 if(id[i]==0) 275 s.push(i); 276 } 277 if(s.size()!=1) OK=false; 278 int count=0; 279 while(!s.empty()){ 280 int v=s.top(); s.pop(); count++; 281 order.push_back(v); 282 list<int>::iterator k; 283 for(k=g[v].begin();k!=g[v].end();k++){ 284 id[*k]--; 285 if(id[*k]==0) s.push(*k); 286 if(s.size()>1) OK=false; 287 } 288 } 289 if(order.size() < n) OK=false; //矛盾发生,会导致这种情况,小心 290 if(count < n) incon=true; 291 copy(&t[0],&t[n],&id[0]); 292 } 293 DFS强连通分支 294 #include <iostream> 295 #include <algorithm> 296 #include <vector> 297 using namespace std; 298 #define M 20005 299 vector<int> g[M],gt[M]; 300 bool used[M]; 301 int ft[M],sort_v[M],tim; 302 bool comp(const int &u,const int &v){ 303 return ft[u]>ft[v]; 304 } 305 inline int findp(int set[],int n){ 306 int n2=n; 307 while(set[n]!=0) n=set[n]; 308 if(n2!=n) set[n2]=n; 309 return n; 310 } 311 inline bool uni(int set[],int a,int b){ 312 int ac=0,a2=a,b2=b,bc=0,t; 313 while(set[a]!=0) {a=set[a];ac++;} 314 while(a2!=a) {t=set[a2]; set[a2]=a; a2=t;}; 315 while(set[b]!=0) {b=set[b];bc++;} 316 while(b2!=b) {t=set[b2]; set[b2]=b; b2=t;}; 317 if(a==b) return false; 318 if(ac<bc) set[a]=b; 319 else set[b]=a; 320 return true; 321 } 322 void dfs(vector<int> g[M],int u){ 323 if(used[u]) return; 324 tim++; 325 used[u]=true; 326 int i; 327 for(i=0;i<g[u].size();i++){ 328 dfs(g,g[u][i]); 329 } 330 tim++; 331 ft[u]=tim; 332 return; 333 } 334 void dfs2(vector<int> g[],int u,int r,int set[]){ 335 if(used[u]) return; 336 uni(set,u,r); 337 used[u]=true; 338 int i; 339 for(i=0;i<g[u].size();i++){ 340 dfs2(g,g[u][i],u,set); 341 } 342 return; 343 } 344 void scc(int n,vector<int> g[M],int set[]){ 345 int i,j; 346 tim=0; 347 memset(used,0,sizeof(used)); 348 memset(set,0,sizeof(set)); 349 for(i=1;i<=n;i++) sort_v[i]=i; 350 for(i=1;i<=n;i++) if(!used[i]) dfs(g,i); //compute finishing times 351 sort(&sort_v[1],&sort_v[n+1],comp); //decreasing f[u] order 352 memset(used,0,sizeof(used)); 353 for(i=1;i<=n;i++) for(j=0;j<g[i].size();j++) gt[g[i][j]].push_back(i); //compute gt 354 for(i=1;i<=n;i++) if(!used[sort_v[i]]) dfs2(gt,sort_v[i],sort_v[i],set); //make the scc 355 } 356 int main(){ 357 int i,j,n,m,u,v,set[M]; 358 cin >> n >> m; 359 for(i=0;i<m;i++){ 360 scanf("%d%d",&u,&v); 361 g[u].push_back(v); 362 } 363 scc(n,g,set); 364 int pi=1,ptosc[M]; 365 struct Scc{ 366 int p,n; 367 }sc[M]; 368 memset(sc,0,sizeof(sc)); 369 for(i=1;i<=n;i++){ 370 int p=findp(set,i); 371 if(sc[p].p==0) {sc[p].p=pi; ptosc[pi++]=p;} 372 sc[p].n++; 373 } 374 int n2=pi-1,od[M]; 375 memset(od,0,sizeof(od)); 376 for(i=1;i<=n;i++){ 377 for(j=0;j<g[i].size();j++){ 378 u=findp(set,i); v=findp(set,g[i][j]); 379 if(sc[u].p!=sc[v].p) od[sc[u].p]++; 380 } 381 } 382 int sum=0,s1=0; 383 for(i=1;i<=n2;i++) if(od[i]==0) {s1++; sum+=sc[ptosc[i]].n;} 384 if(s1!=1) sum=0; 385 cout << sum << endl; 386 } 387 最大匹配 388 #include <iostream> 389 #include <string> 390 #include <math.h> 391 using namespace std; 392 #define M 1001 393 394 int n,m,match[M],ans[M]; 395 bool visit[M],g[M][M]; 396 //O(n^3) 397 bool dfs(int k,bool map[M][M]){ 398 int t; 399 for(int i = 1; i <= m; i++){ 400 if(map[k][i] && !visit[i]){ 401 visit[i] = true; 402 t = match[i]; 403 match[i] = k; 404 if(t == 0 || dfs(t,map)) 405 return true; 406 match[i] = t; 407 } 408 } 409 return false; 410 } 411 int main(){ 412 int i,sum=0,t,j,u,v; 413 cin >> t; 414 while(t--){ 415 sum=0; 416 memset(match,0,sizeof(match)); 417 memset(g,0,sizeof(g)); 418 scanf("%d%d",&n,&m); 419 for(i=1;i<=m;i++){ 420 scanf("%d%d",&u,&v); 421 g[u][v]=true; 422 } 423 m=n; 424 for(i=1;i<=n; i++){ 425 memset(visit,0,sizeof(visit)); 426 if(dfs(i,g)) sum++; 427 } 428 cout << n-sum << endl; 429 } 430 return 0; 431 } 432 还有两个最大匹配模板 433 #include <iostream> 434 #include <string> 435 #include <math.h> 436 #include <vector> 437 using namespace std; 438 #define M 3001 439 440 bool g[M][M]; 441 int mk[M] ,cx[M],pred[M],open[M],cy[M],nx,ny; 442 443 444 //边少适用O(n^3) 445 int MaxMatchBFS() 446 { 447 int i , u , v , t , d , e , cur , tail , res(0) ; 448 memset(mk , 0xff , sizeof(mk)) ; 449 memset(cx , 0xff , sizeof(cx)) ; 450 memset(cy , 0xff , sizeof(cy)) ; 451 for (i = 0 ; i < nx ; i++){ 452 pred[i] = -1 ; 453 for (open[cur = tail = 0] = i ; cur <= tail && cx[i] == -1 ; cur++){ 454 for (u = open[cur] , v = 0 ; v < ny && cx[i] == -1 ; v ++) if (g[u][v] && mk[v] != i) 455 { 456 mk[v] = i ; open[++tail] = cy[v] ; if (open[tail] >= 0) { pred[open[tail]] = u ; continue ; } 457 for (d = u , e = v ; d != -1 ; t = cx[d] , cx[d] = e , cy[e] = d , e = t , d = pred[d]) ; 458 } 459 } 460 if (cx[i] != -1) res++ ; 461 } 462 return res ; 463 } 464 465 int path(int u){ 466 for (int v = 0 ; v < ny ; v++) 467 if (g[u][v] && !mk[v]){ 468 mk[v] = 1 ; 469 if (cy[v] == -1 || path(cy[v])) { 470 cx[u] = v ; 471 cy[v] = u ; 472 return 1 ; 473 } 474 } return 0 ; 475 } 476 //少适用O(n^3) 477 int MaxMatchDFS() 478 { 479 int res(0) ; 480 memset(cx , 0xff , sizeof(cx)) ; 481 memset(cy , 0xff , sizeof(cy)) ; 482 for (int i = 0 ; i < nx ; i++) 483 if (cx[i] == -1){ 484 memset(mk , 0 , sizeof(mk)); 485 res += path(i) ; 486 } 487 return res ; 488 } 489 最大权匹配,KM算法 490 //此KM算法,坐标从1开始,记住 491 #include <iostream> 492 #include <vector> 493 #include <math.h> 494 using namespace std; 495 #define M 110 496 497 int n; // X 的大小 498 int lx[M], ly[M]; // 标号 499 bool sx[M], sy[M]; // 是否被搜索过 500 int match[M]; // Y(i) 与 X(match [i]) 匹配 501 502 // 从 X(u) 寻找增广道路,找到则返回 true 503 bool path(int u,int weight[M][M]) { 504 sx [u] = true; 505 for (int v = 0; v < n; v ++) 506 if (!sy [v] && lx[u] + ly [v] == weight [u] [v]) { 507 sy [v] = true; 508 if (match [v] == -1 || path(match [v],weight)) { 509 match [v] = u; 510 return true; 511 } 512 } 513 return false; 514 } 515 // 参数 Msum 为 true ,返回最大权匹配,否则最小权匹配 516 int km(bool Msum,int weight[M][M]) { 517 int i, j; 518 if (!Msum) { 519 for (i = 0; i < n; i ++) 520 for (j = 0; j < n; j ++) 521 weight [i] [j] = -weight [i] [j]; 522 } 523 // 初始化标号 524 for (i = 0; i < n; i ++) { 525 lx [i] = -0x1FFFFFFF; 526 ly [i] = 0; 527 for (j = 0; j < n; j ++) 528 if (lx [i] < weight [i] [j]) 529 lx [i] = weight [i] [j]; 530 } 531 memset(match, -1, sizeof (match)); 532 for (int u = 0; u < n; u ++) 533 while (1) { 534 memset(sx, 0, sizeof (sx)); 535 memset(sy, 0, sizeof (sy)); 536 if (path(u,weight)) 537 break; 538 // 修改标号 539 int dx = 0x7FFFFFFF; 540 for (i = 0; i < n; i ++) 541 if (sx [i]) 542 for (j = 0; j < n; j ++) 543 if(!sy [j]) 544 dx = min(lx[i] + ly [j] - weight [i] [j], dx); 545 for (i = 0; i < n; i ++) { 546 if (sx [i]) 547 lx [i] -= dx; 548 if (sy [i]) 549 ly [i] += dx; 550 } 551 } 552 553 int sum = 0; 554 for (i = 0; i < n; i ++) 555 sum += weight [match [i]] [i]; 556 557 if (!Msum) { 558 sum = -sum; 559 for (i = 0; i < n; i ++) 560 for (j = 0; j < n; j ++) 561 weight [i] [j] = -weight [i] [j]; // 如果需要保持 weight [ ] [ ] 原来的值,这里需要将其还原 562 } 563 return sum; 564 } 565 566 struct Point{ 567 int r,c; 568 }; 569 int main(){ 570 int i,j,m; 571 freopen("in","r",stdin); 572 int w[M][M]; 573 char c; Point pt; 574 while(cin >> n >> m && (n!=0 || m!=0)){ 575 vector<Point> vh,vm; 576 for(i=0;i<n;i++){ 577 getchar(); 578 for(j=0;j<m;j++){ 579 scanf("%c",&c); 580 if(c=='H'){ 581 pt.r=i; pt.c=j; 582 vh.push_back(pt); 583 } 584 if(c=='m'){ 585 pt.r=i;pt.c=j; 586 vm.push_back(pt); 587 } 588 } 589 } 590 for(i=0;i<vm.size();i++) for(j=0;j<vh.size();j++) w[i][j]=abs(vm[i].r-vh[j].r)+abs(vm[i].c-vh[j].c); 591 n=vm.size(); 592 cout << km(false,w)<< endl; 593 } 594 } 595 两种欧拉路 596 无向图: 597 #define M 45 598 int used[M][M],id[M]; 599 void dfs(int u,vector<int> g[],vector<int> &vans){ //O(E^2) 600 int j,w,v,t; 601 for(j=g[u].size()-1;j>=0;j--){ 602 t=v=g[u][j]; w=u; 603 if(v>w) swap(v,w); 604 if(used[v][w]!=0){ 605 used[v][w]--; 606 dfs(t,g,vans); 607 } 608 } 609 vans.push_back(u); 610 } 611 612 有向图: 613 int n,m; 614 vector<int> g[M],vans; 615 void dfs(int u){ //O(E^2*log(e)) 616 int j,t; 617 Edg et; 618 for(j=g[u].size()-1;j>=0;j--){ 619 et.u=u; et.v=g[u][j]; 620 if(mp[et]!=0){ 621 mp[et]--; 622 dfs(g[u][j]); 623 } 624 } 625 vans.push_back(u); 626 } 627 628 【最大流】Edmonds Karp 629 //求最小割集合的办法: 630 //设置一个集合A, 最开始A={s},按如下方法不断扩张A: 631 //1 若存在一条边(u,v), 其流量小于容量,且u属于A,则v加入A 632 //2 若存在(v,u), 其流量大于0,且u属于A,则v加入A 633 634 //A计算完毕,设B=V-A, 635 //最大流对应的割集E={(u,v) | u∈A,v∈B} 636 //E为割集,这是一定的 637 638 //【最大流】Edmonds Karp算法求最大流,复杂度 O(V E^2)。返回最大流,输入图容量 639 //矩阵g[M][M],取非零值表示有边,s为源点,t为汇点,f[M][M]返回流量矩阵。 640 641 int f[M][M],g[M][M]; 642 643 int EdmondsKarp(int n,int s,int t){ 644 int i,j,k,c,head,tail,flow=0; 645 int r[M][M]; 646 int prev[M],visit[M],q[M]; 647 for (i=1;i<=n;i++) for (j=1;j<=n;j++) {f[i][j]=0;r[i][j]=g[i][j];} //初始化流量网络和残留网络 648 while (1) { //在残留网络中找到一条s到t的最短路径 649 head=tail=0; 650 memset(visit,0,sizeof(visit)); 651 q[tail++]=s; 652 prev[s]=-1; visit[s]=1; 653 while(head!=tail){ //宽度优先搜索从s到t的最短路径 654 k=q[head++]; 655 for (i=1;i<=n;i++) 656 if (!visit[i] && r[k][i]>0) { 657 visit[i]=1; 658 prev[i]=k; 659 if (i==t) goto next; 660 q[tail++]=i; 661 } 662 } 663 next: 664 if (!visit[t]) break; //流量已达到最大 665 c=99999999; 666 j=t; 667 while (j!=s) { 668 i=prev[j]; 669 if (c>r[i][j]) c=r[i][j]; 670 j=i; 671 } 672 //下面改进流量 673 j=t; 674 while (j!=s) { 675 i=prev[j]; 676 f[i][j]+=c; 677 f[j][i]=-f[i][j]; 678 r[i][j]=g[i][j]-f[i][j]; 679 r[j][i]=g[j][i]-f[j][i]; 680 j=i; 681 } 682 flow+=c; 683 //cout << c << endl; 684 } 685 return flow; 686 } 687 dinic 688 /* 689 dinic 690 BFS+多路增广 691 这个模板是OIBH上的Code_Rush的,他写的Dinic和别人的不太一样,速度更快 692 O(mn^2) 693 */ 694 695 #include<stdio.h> 696 #include<list> 697 #include<queue> 698 #include<string.h> 699 #include <vector> 700 #include <iostream> 701 using namespace std; 702 #define M 201 703 int pre[M]; 704 int f[M][M],g[M][M]; 705 bool b[M]={0}; 706 707 //g为输入的图容量矩阵,f为返回流量矩阵 708 int dinic(int n,int s,int t) 709 { 710 memset(f,0,sizeof(f)); 711 int ans=0; 712 while(true) 713 { 714 queue<int> q; 715 fill(pre,pre+n+2,-1); 716 fill(b,b+n+2,0); 717 q.push(s);b[s]=1; 718 while(!q.empty()) 719 { 720 int x=q.front();q.pop(); 721 if(x==t)break; 722 for(int i=1;i<=n;i++) 723 { 724 if(!b[i]&&f[x][i]<g[x][i]) 725 { 726 pre[i]=x; 727 b[i]=1; 728 q.push(i); 729 } 730 } 731 } 732 if(pre[t]==-1)break; 733 for(int i=1;i<=n;i++) 734 { 735 if(f[i][t]<g[i][t]&&(i==s||pre[i]!=-1)) 736 { 737 int v,low=g[i][t]-f[i][t]; 738 pre[t]=i; 739 for(v=t;pre[v]!=-1;v=pre[v]) 740 low=low<g[pre[v]][v]-f[pre[v]][v]?low:g[pre[v]][v]-f[pre[v]][v]; 741 if(low==0)continue; 742 for(v=t;pre[v]!=-1;v=pre[v]) 743 { 744 f[pre[v]][v]+=low; 745 f[v][pre[v]]-=low; 746 } 747 ans+=low; 748 } 749 } 750 } 751 return ans; 752 } 753 754 int main(){ 755 int m,n,i,j,u,v,w; 756 while(cin >> m >> n){ 757 memset(g,0,sizeof(g)); 758 for(i=0;i<m;i++){ 759 scanf("%d%d%d",&u,&v,&w); 760 g[u][v]+=w; 761 } 762 cout << dinic(n,1,n) << endl; 763 } 764 } 765 【最小费用最大流】Edmonds Karp对偶算法 766 #define M 211 767 #define LIM 99999999 768 //【最小费用最大流】Edmonds Karp对偶算法,复杂度 O(V^3E^2)。返回最大流,输入图 769 //容量矩阵g[M][M],费用矩阵w[M][M],取非零值表示有边,s为源点,t为汇点,f[M][M]返 770 //回流量矩阵,minw返回最小费用。 771 int g[M][M],w[M][M],minw,f[M][M]; 772 int DualityEdmondsKarp(int n,int s,int t){ 773 int i,j,k,c,quit,flow=0; 774 int best[M],prev[M]; 775 minw=0; 776 for (i=1;i<=n;i++) { 777 for (j=1;j<=n;j++){ 778 f[i][j]=0; 779 if (g[i][j]) {g[j][i]=0;w[j][i]=-w[i][j];} 780 } 781 } 782 while (1) { 783 for (i=1;i<=n;i++) best[i]=LIM; 784 best[s]=0; 785 do { 786 quit=1; 787 for (i=1;i<=n;i++){ 788 if (best[i]<LIM) 789 for (j=1;j<=n;j++){ 790 if (f[i][j]<g[i][j] && best[i]+w[i][j]<best[j]){ 791 best[j]=best[i]+w[i][j]; 792 prev[j]=i; 793 quit=0; 794 } 795 } 796 } 797 }while(!quit); 798 if (best[t]>=LIM) break; 799 c=LIM; 800 j=t; 801 while (j!=s) { 802 i=prev[j]; 803 if (c>g[i][j]-f[i][j]) c=g[i][j]-f[i][j]; 804 j=i; 805 } 806 j=t; 807 while (j!=s) { 808 i=prev[j]; 809 f[i][j]+=c; 810 f[j][i]=-f[i][j]; 811 j=i; 812 } 813 flow+=c; minw+=c*best[t]; 814 } 815 return flow; 816 }

你可能感兴趣的:(acm 常用算法)