终于会最大流了,简直尿

我终于会最大流啦!以前(若干年前)认真背过ISAP+GAP优化+当前弧优化的超碉模板,不过一次都没用过!

这次我找到了当年的模板,还是pascal的…我怒写了一份C++的。

然后过了一道最大流裸奔题Drainage Ditches(http://poj.org/problem?id=1273)。

然后我又找了一道水题

这题要分点,把一个点分成入点和出点,两个点之间连一条这个点的消耗的边。然后之后它给的边(x,y)就把x的出点和y的入点连起来。这题的河居然可以两个方向流,(y,x)也要连一发……然后改一下出发点和结束点就行了,哐哐哐就是过。

 

以前学的时候,看网上说ISAP+GAP+当前弧是最碉的最大流算法,怒虐dinic,有没有很碉。

代码:

ISAP+GAP+当前弧:

 1 //ISAP+当前弧+GAP,邻接矩阵,起点为1终点为n,先输入m再输入n
 2 #include<iostream>
 3 #include<cstdio>
 4 #include<cstring>
 5 using namespace std;
 6 
 7 const int MAXN=222;//点数
 8 const int inf=0x7fffffff;//MAXINT
 9 
10 int c[MAXN][MAXN],h[MAXN],g[MAXN],d[MAXN];//c为残留容量邻接矩阵
11 //g[i]为标号为i的结点个数,h[i]为i结点的标号
12 //d[]当前弧优化,记录当前弧
13 bool found;
14 int n,m,st,ed,augc,flow;//n个点m条边,augc为增广路容量,flow为最大流
15 
16 void aug(const int m)
17 {
18     int i,augco=augc,mini,minh=n-1;
19     if (m==ed)//如果当前结点为汇点
20     {
21         found=true;
22         flow+=augc;    //增加流量
23         return;
24     }
25     for (i=d[m]; i<=n; i++)//寻找容许边
26         if (c[m][i]>0 && h[i]+1==h[m])//如果残留容量大于0,如果是容许边
27         {
28             if (c[m][i]<augc)  augc=c[m][i];//如果容许边流量小于当前增广路流量 则更新增广路流量
29             d[m]=i;    //把i定为当前弧
30             aug(i);    //递归
31             if (h[1]>=n) return; //GAP 如果源点距离标号大于n 则停止算法
32             if (found) break;    //如果找到汇点 则退出寻找
33             augc=augco;//没找到就还原当前的流
34         }
35     if (!found)        //重标号
36     {
37         for (i=1; i<=n; i++) //找那个标号,这里不能用d[m]开始,不然会蛋疼
38             if (c[m][i]>0 && h[i]<minh)
39             {
40                 minh=h[i];
41                 mini=i;
42             }
43         g[h[m]]--;                                 //GAP 距离为
44         if (g[h[m]]==0) h[1]=n;                 //GAP
45         h[m]=minh+1;
46         d[m]=mini;
47         g[h[m]]++;                                 //GAP
48     }
49     else
50     {//修改残量
51         c[m][i]-=augc;
52         c[i][m]+=augc;
53     }
54 }
55 
56 void farm()
57 {
58     int i,j,x,y,z;
59     memset(c,0,sizeof(c));
60     for(i=0; i<m; i++)
61     {
62         scanf("%d%d%d",&x,&y,&z);
63         c[x][y]+=z;
64     }
65     st=1;ed=n;
66     memset(h,0,sizeof(h));
67     memset(g,0,sizeof(g));
68     g[0]=n;
69     flow=0;
70     for(i=1; i<=n; i++)
71         d[i]=1;//当前弧初始化
72     while(h[1]<n)
73     {
74         augc=inf;//初始化增广路容量为正无穷大
75         found=false;
76         aug(1);//从源点开始找
77     }
78     printf("%d\n",flow);
79 }
80 
81 int main()
82 {
83     while(scanf("%d%d",&m,&n)!=EOF) farm();
84     return 0;
85 }
View Code

笨笨的洪水渡劫:

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 using namespace std;
  5 
  6 const int MAXN=444;
  7 const int MAXM=444;
  8 const int inf=0x7fffff;
  9 
 10 int c[MAXN][MAXN];//残留容量邻接矩阵
 11 
 12 int h[MAXN],g[MAXN];//g[i]为标号为i的结点个数 h[i]为i结点的标号
 13 int augc,flow;//augc为增广路容量,flow为最大流
 14 bool found;
 15 int d[MAXN];//当前弧优化,记录当前弧
 16 int st,ed;
 17 
 18 int n,m;//n个点m条边
 19 
 20 
 21 void aug(const int m)
 22 {
 23     int i,augco=augc,mini,minh=n-1;
 24     if (m==ed)//如果当前结点为汇点
 25     {
 26         found=true;
 27         flow+=augc;    //增加流量
 28         return;
 29     }
 30     for (i=d[m]; i<=n; i++)//寻找容许边
 31         if (c[m][i]>0 && h[i]+1==h[m])//如果残留容量大于0,如果是容许边
 32         {
 33             if (c[m][i]<augc)  augc=c[m][i];//如果容许边流量小于当前增广路流量 则更新增广路流量
 34             d[m]=i;    //把i定为当前弧
 35             aug(i);    //递归
 36             if (h[1]>=n) return; //GAP 如果源点距离标号大于n 则停止算法
 37             if (found) break;    //如果找到汇点 则退出寻找
 38             augc=augco;//没找到就还原当前的流
 39         }
 40     if (!found)        //重标号
 41     {
 42         for (i=1; i<=n; i++) //找那个标号,这里不能用d[m]开始,不然会蛋疼
 43             if (c[m][i]>0 && h[i]<minh)
 44             {
 45                 minh=h[i];
 46                 mini=i;
 47             }
 48         g[h[m]]--;                                 //GAP 距离为
 49         if (g[h[m]]==0) h[1]=n;                 //GAP
 50         h[m]=minh+1;
 51         d[m]=mini;
 52         g[h[m]]++;                                 //GAP
 53     }
 54     else
 55     {
 56         //修改残量
 57         c[m][i]-=augc;
 58         c[i][m]+=augc;
 59     }
 60 }
 61 
 62 void farm()
 63 {
 64     int i,j,x,y,z;
 65     memset(c,0,sizeof(c));
 66     scanf("%d%d",&n,&m);
 67     for(i=2;i<=n;i++)
 68     {
 69         scanf("%d",&x);
 70         c[i][i+n+1]+=x;
 71     }
 72     c[1][n+2]+=inf;
 73     for(i=0; i<m; i++)
 74     {
 75         scanf("%d%d",&x,&y);
 76         x++;y++;
 77         c[x+n+1][y]+=inf;
 78         c[y+n+1][x]+=inf;
 79     }
 80     st=1;ed=n+1;
 81     n+=n+1;
 82 //    for(i=1;i<=n;i++)
 83 //    {
 84 //        for(j=1;j<=n;j++)
 85 //            cout<<c[i][j]<<' ';
 86 //        cout<<endl;
 87 //    }
 88     memset(h,0,sizeof(h));
 89     memset(g,0,sizeof(g));
 90     g[0]=n;
 91     flow=0;
 92     for(i=1; i<=n; i++)
 93         d[i]=1;//当前弧初始化
 94     while(h[1]<n)
 95     {
 96         augc=inf;//初始化增广路容量为正无穷大
 97         found=false;
 98         aug(st);//从源点开始找
 99     }
100     if(flow>=inf) printf("Max!\n");
101         else if(flow==0) printf("Min!\n");
102         else printf("%d\n",flow);
103 }
104 
105 int main()
106 {
107     int T;
108     scanf("%d",&T);
109     while(T--) farm();
110     return 0;
111 }
View Code

 

posted @ 2014-05-28 17:35  带鱼Yuiffy  阅读(171)  评论(0编辑  收藏  举报