我爱网络流之最大流Dinic

直接上大佬博客:

Dinic算法详解及实现来自小菲进修中

Dinic算法(研究总结,网络流)来自SYCstudio

  模板步骤:

  第一步,先bfs把图划分成分成分层图网络

  第二步,dfs多次找增广路

  当前弧优化:即每一次dfs增广时不从第一条边开始,而是用一个数组cur记录点u之前循环到了哪一条边,以此来加速

POJ - 1273 Drainage Ditches

   裸的最大流,直接按题意建图跑就行

 1 #include<cstdio>
 2 #include<queue>
 3 #include<algorithm>
 4 using namespace std;
 5 const int N=218,inf=2000000007;
 6 struct Side{
 7     int v,ne,w;
 8 }S[N<<1];
 9 int n,sn,head[N],cur[N],dep[N];
10 void init()
11 {
12     sn=0;
13     for(int i=0;i<=n;i++)
14         head[i]=-1;
15 }
16 void add(int u,int v,int w)
17 {
18     S[sn].v=v;
19     S[sn].w=w;
20     S[sn].ne=head[u];
21     head[u]=sn++;
22 }
23 void addE(int u,int v,int w)
24 {
25     add(u,v,w);
26     add(v,u,0);
27 }
28 bool bfs()
29 {
30     queue<int> q;
31     for(int i=0;i<=n;i++)
32         dep[i]=0;
33     dep[1]=1;
34     q.push(1);
35     int x,y;
36     while(!q.empty())
37     {
38         x=q.front();
39         q.pop();
40         for(int i=head[x];~i;i=S[i].ne)
41         {
42             y=S[i].v;
43             if(S[i].w>0&&!dep[y])
44             {
45                 dep[y]=dep[x]+1;
46                 q.push(y);
47             }
48         }
49     }
50     return dep[n]!=0;
51 }
52 int dfs(int u,int minf)
53 {
54     if(u==n||!minf)
55         return minf;
56     int v,flow;
57     for(int &i=cur[u];~i;i=S[i].ne)
58     {
59         v=S[i].v;
60         if(dep[v]==dep[u]+1&&S[i].w>0)
61         {
62             flow=dfs(v,min(minf,S[i].w));
63             if(flow)
64             {
65                 S[i].w-=flow;
66                 S[i^1].w+=flow;
67                 return flow;
68             }
69         }
70     }
71     return 0;
72 }
73 int dinic()
74 {
75     int ans=0,flow;
76     while(bfs())
77     {
78         for(int i=1;i<=n;i++)
79             cur[i]=head[i];
80         while(flow=dfs(1,inf))
81             ans+=flow;
82     }
83     return ans;
84 }
85 int main()
86 {
87     int m,u,v,w;
88     while(~scanf("%d%d",&m,&n))
89     {
90         init();
91         while(m--)
92         {
93             scanf("%d%d%d",&u,&v,&w);
94             addE(u,v,w);
95         }
96         printf("%d\n",dinic());
97     }
98     return 0;
99 }
小桥流水人家

POJ - 1698Alice's Chance

  也是个裸的最大流,不过得看得出来,就把每周每天视为节点,然后弄个汇点跟源点,跑一遍dinic看最大流是不是总要求的天数

  1 #include<cstdio>
  2 #include<queue>
  3 #include<algorithm>
  4 using namespace std;
  5 const int N=6118,inf=2000000007;
  6 struct Side{
  7     int v,ne,w;
  8 }S[N<<1];
  9 struct Film{
 10     int ok[8],day,week;
 11 }F[N];
 12 int n,sn,sum,sb,se,head[N],cur[N],dep[N];
 13 void init()
 14 {
 15     sn=0,sum=0;
 16     sb=0,se=n+351;
 17     for(int i=0;i<=se;i++)
 18         head[i]=-1;
 19 }
 20 void add(int u,int v,int w)
 21 {
 22     S[sn].v=v;
 23     S[sn].w=w;
 24     S[sn].ne=head[u];
 25     head[u]=sn++;
 26 }
 27 void addE(int u,int v,int w)
 28 {
 29     add(u,v,w);
 30     add(v,u,0);
 31 }
 32 bool bfs()
 33 {
 34     queue<int> q;
 35     for(int i=0;i<=se;i++)
 36         dep[i]=0;
 37     dep[sb]=1;
 38     q.push(sb);
 39     int u,v;
 40     while(!q.empty())
 41     {
 42         u=q.front();
 43         q.pop();
 44         for(int i=head[u];~i;i=S[i].ne)
 45         {
 46             v=S[i].v;
 47             if(S[i].w>0&&!dep[v])
 48             {
 49                 dep[v]=dep[u]+1;
 50                 q.push(v); 
 51             }
 52         }
 53     }
 54     return dep[se]!=0;
 55 }
 56 int dfs(int u,int minf)
 57 {
 58     if(u==se||!minf)
 59         return minf;
 60     int v,flow;
 61     for(int &i=cur[u];~i;i=S[i].ne)
 62     {
 63         v=S[i].v;
 64         if(S[i].w>0&&dep[v]==dep[u]+1)
 65         {
 66             flow=dfs(v,min(minf,S[i].w));
 67             if(flow>0)
 68             {
 69                 S[i].w-=flow;
 70                 S[i^1].w+=flow;
 71                 return flow;
 72             }
 73         }
 74     }
 75     return 0;
 76 }
 77 int dinic()
 78 {
 79     int ans=0,flow;
 80     while(bfs())
 81     {
 82         for(int i=0;i<=se;i++)
 83             cur[i]=head[i];
 84         while(flow=dfs(sb,inf))
 85             ans+=flow;
 86     }
 87     return ans;
 88 }
 89 int main()
 90 {
 91     int t;
 92     scanf("%d",&t);
 93     while(t--)
 94     {
 95         scanf("%d",&n);
 96         init();
 97         for(int i=1;i<=n;i++)
 98         {
 99             for(int j=1;j<=7;j++)
100                 scanf("%d",&F[i].ok[j]);
101             scanf("%d%d",&F[i].day,&F[i].week);
102             sum+=F[i].day;
103         }
104         for(int i=1;i<=n;i++)
105             addE(sb,i,F[i].day);
106         for(int i=1;i<=n;i++)
107         {
108             for(int j=0;j<F[i].week;j++)
109                 for(int k=1;k<=7;k++)
110                     if(F[i].ok[k])
111                         addE(i,n+j*7+k,1);
112         }
113         for(int i=0;i<50;i++)
114             for(int j=1;j<=7;j++)
115                 addE(n+i*7+j,se,1);
116         if(dinic()>=sum)
117             printf("Yes\n");
118         else
119             printf("No\n");
120     }
121     return 0;
122 }
one day day

HDU 3605Escape

  100000个人,但才10个星球,在建图上,把可以去的星球状态相同的人视为一样的,这样最多就才1024个状态,然后跑一遍dinic,c++直接交,g++的话得用快读。

  1 #include<cstdio>
  2 #include<queue>
  3 #include<algorithm>
  4 using namespace std;
  5 const int N=1<<12,inf=1000000007;
  6 struct Side{
  7     int v,ne,w;
  8 }S[N<<2];
  9 int sn,pb,pe,n,m,head[N],cur[N];
 10 int cf2[12]={1},man[N],dep[N];
 11 //int read()
 12 //{
 13 //    int res = 0, flg = 1; char chr = getchar();
 14 //    while(chr < '0' || chr > '9') {if(chr == '-') res = -1; chr = getchar();}
 15 //    while(chr <= '9' && chr >= '0') {res = res * 10 + chr - '0'; chr = getchar();}
 16 //    return res * flg;
 17 //}g++用快读 
 18 void init()
 19 {
 20     sn=0;
 21     pb=0,pe=cf2[m]+m;
 22     for(int i=0;i<cf2[m];i++)
 23         man[i]=0;
 24     for(int i=0;i<=pe;i++)
 25         head[i]=-1;
 26 }
 27 void add(int u,int v,int w)
 28 {
 29     S[sn].w=w;
 30     S[sn].v=v;
 31     S[sn].ne=head[u];
 32     head[u]=sn++; 
 33 }
 34 void addE(int u,int v,int w)
 35 {
 36     add(u,v,w);
 37     add(v,u,0);
 38 }
 39 bool bfs()
 40 {
 41     for(int i=0;i<=pe;i++)
 42         dep[i]=0;
 43     dep[pb]=1;
 44     queue<int> q;
 45     q.push(pb);
 46     int u,v;
 47     while(!q.empty())
 48     {
 49         u=q.front();
 50         q.pop();
 51         for(int i=head[u];~i;i=S[i].ne)
 52         {
 53             v=S[i].v;
 54             if(S[i].w>0&&!dep[v])
 55             {
 56                 dep[v]=dep[u]+1;
 57                 q.push(v);
 58             }
 59         }
 60     }
 61     return dep[pe]!=0;
 62 }
 63 int dfs(int u,int minf)
 64 {
 65     if(u==pe||!minf)
 66         return minf;
 67     int v,flow;
 68     for(int &i=cur[u];~i;i=S[i].ne)
 69     {
 70         v=S[i].v;
 71         if(S[i].w>0&&dep[v]==dep[u]+1)
 72         {
 73             flow=dfs(v,min(minf,S[i].w));
 74             if(flow)
 75             {
 76                 S[i].w-=flow;
 77                 S[i^1].w+=flow;
 78                 return flow;
 79             }
 80         }
 81     }
 82     return 0;
 83 }
 84 int dinic()
 85 {
 86     int maxf=0,flow;
 87     while(bfs())
 88     {
 89         for(int i=0;i<=pe;i++)
 90             cur[i]=head[i];
 91         while(flow=dfs(pb,inf))
 92             maxf+=flow;
 93     }
 94     return maxf;
 95 }
 96 int main()
 97 {
 98     for(int i=1;i<=10;i++)
 99         cf2[i]=cf2[i-1]<<1;
100     int num,x;
101     while(~scanf("%d%d",&n,&m))
102     {
103         init();
104         for(int i=1;i<=n;i++)
105         {
106             num=0;
107             for(int j=0;j<m;j++)
108             {
109                 scanf("%d",&x);
110                 if(x)
111                     num|=cf2[j];
112             }
113             man[num]++;
114         }
115         for(int i=1;i<cf2[m];i++)
116             if(man[i])
117             {
118                 addE(pb,i,man[i]);
119                 for(int j=0;j<m;j++)
120                     if(i&cf2[j])
121                         addE(i,cf2[m]+j,man[i]);
122             }
123         for(int i=0;i<m;i++)
124         {
125             scanf("%d",&x);
126             addE(cf2[m]+i,pe,x);
127         }
128         if(dinic()>=n)
129             printf("YES\n");
130         else
131             printf("NO\n");
132     }
133     return 0;
134 }
流浪星球

  啊,网络流就在于建图。

 

posted @ 2019-06-11 15:43  新之守护者  阅读(152)  评论(0编辑  收藏  举报