网络流——最大流、最大流最小割定理

最大流:

http://blog.csdn.net/brodrinkwater/article/details/54999932

https://www.cnblogs.com/LUO77/p/6115057.html

 1 //ek算法 
 2 #include<algorithm>
 3 #include<iostream>
 4 #include<cstdlib>
 5 #include<cstring>
 6 #include<cstdio>
 7 #include<cmath>
 8 #include<queue>
 9 #define ll long long
10 using namespace std;
11 int n,m,sum;
12 int c[501][501],r[501][501],p[501],pre[501];
13 void find(){
14     queue<int>q;
15     while(1){
16         q.push(1);
17         memset(p,0,sizeof(p));
18         p[1]=9999999;
19         while(!q.empty()){
20             int ans=q.front();
21             q.pop();
22             for(int i=1;i<=n;i++){
23                 if(!p[i] && r[ans][i]<c[ans][i]){
24                     p[i]=min(p[ans],c[ans][i]-r[ans][i]);
25                     pre[i]=ans;
26                     q.push(i);
27                 }
28             }
29         }      
30         if(!p[n])break;
31         sum+=p[n];
32         int tmp=n;
33         while(pre[tmp]){
34             r[pre[tmp]][tmp]+=p[n];
35             r[tmp][pre[tmp]]-=p[n];
36             tmp=pre[tmp];
37         }
38         
39     }
40     return ;
41 }
42 int main(){
43     scanf("%d%d",&n,&m);
44     for(int i=1;i<=m;i++){
45         int x,y,z;
46         scanf("%d%d%d",&x,&y,&z);
47         c[x][y]+=z;
48     }
49     find();
50     printf("%d",sum);
51     return 0;
52 }
View Code
 1 #include<algorithm>
 2 //dinic算法 
 3 #include<iostream>
 4 #include<cstdlib>
 5 #include<cstring>
 6 #include<cstdio>
 7 #include<cmath>
 8 #include<queue>
 9 #define ll long long
10 using namespace std;
11 int m,n,ans;
12 struct edge
13 {
14     int to,next,f;
15 }e[200005];
16 int head[20005],p;
17 void addedge(int u,int v,int f)
18 {
19     e[p].to=v;e[p].f=f;e[p].next=head[u];head[u]=p;p++;
20     e[p].to=u;e[p].f=0;e[p].next=head[v];head[v]=p;p++;
21 }
22 int level[20005];
23 bool bfs(int s,int t)
24 {
25     memset(level,0,sizeof(level));
26     queue<int> q;
27     q.push(s);
28     level[s]=1;
29     while(!q.empty())
30     {
31         int u=q.front();
32         q.pop();
33         if(t==u)return 1;
34         for(int i=head[u];i!=-1;i=e[i].next)
35         {
36             int v=e[i].to,f=e[i].f;
37             if(level[v]==0 && f!=0){
38                 q.push(v);
39                 level[v]=level[u]+1;
40             }
41         }
42     }
43     return 0;
44 }
45 int dfs(int u,int maxf,int t)
46 {
47     if(u==t)return maxf;
48     int tmp=0;
49     for(int i=head[u];i!=-1 && tmp<maxf;i=e[i].next)
50     {
51         int v=e[i].to,f=e[i].f;
52         if(level[v]==level[u]+1 && f!=0)
53         {
54             int minn=min(maxf-tmp,f);
55             f=dfs(v,minn,t);
56             e[i].f-=f;     //正向边 
57             e[i^1].f+=f;    //反向边 
58             //这里的^是很常用的,因为前向星加边是两条一起加的,所以一个标号是奇数,一个是偶数,所以^1一下可以得到另一条边,比如0^1 = 1,1 ^ 1 = 0, 2^1 = 3,3 ^1 = 2;
59             tmp+=f;
60         }
61     }
62     if(!tmp)level[u]=1000000000;
63     return tmp;
64 }
65 void dinic(int s,int t)
66 {
67     while(bfs(s,t)){
68         ans+=dfs(s,1000000000,t);
69     }
70 }
71 int main()
72 {
73     scanf("%d%d",&n,&m);
74     memset(head,-1,sizeof(head));
75     for(int i=1;i<=m;i++)
76     {
77         int u,v,f;
78         scanf("%d%d%d",&u,&v,&f);
79         addedge(u,v,f);
80     }
81     dinic(1,n);
82     printf("%d",ans);
83     return 0;
84 } 
View Code

 

最大流最小割定理:

http://hihocoder.com/problemset/problem/1378

  1 #include<algorithm>
  2 #include<iostream>
  3 #include<cstdlib>
  4 #include<cstring>
  5 #include<cstdio>
  6 #include<cmath>
  7 #include<queue>
  8 #include<vector>
  9 #define ll long long
 10 using namespace std;
 11 
 12 int m,n,ans,head[20005],p,level[20005],sum=0;
 13 bool fa=false; 
 14 
 15 struct edge
 16 {
 17     int to,next,f;
 18 }e[200005];
 19 
 20 vector <int> w;
 21 
 22 void addedge(int u,int v,int f)
 23 {
 24     e[p].to=v;e[p].f=f;e[p].next=head[u];head[u]=p;p++;
 25     e[p].to=u;e[p].f=0;e[p].next=head[v];head[v]=p;p++;
 26 }
 27 
 28 bool bfs(int s,int t)
 29 {
 30     memset(level,0,sizeof(level));
 31     queue<int> q;
 32     q.push(s);
 33     level[s]=1;
 34     if(fa)w.push_back(s);
 35     while(!q.empty())
 36     {
 37         int u=q.front();
 38         q.pop();
 39         if(t==u)return 1;
 40         for(int i=head[u];i!=-1;i=e[i].next)
 41         {
 42             int v=e[i].to,f=e[i].f;
 43             if(level[v]==0 && f!=0){
 44                 q.push(v);
 45                 level[v]=level[u]+1;
 46                 if(fa)w.push_back(v),sum++;
 47             }
 48         }
 49     }
 50     return 0;
 51 }
 52 
 53 int dfs(int u,int maxf,int t)
 54 {
 55     if(u==t)return maxf;
 56     int tmp=0;
 57     for(int i=head[u];i!=-1 && tmp<maxf;i=e[i].next)
 58     {
 59         int v=e[i].to,f=e[i].f;
 60         if(level[v]==level[u]+1 && f!=0)
 61         {
 62             int minn=min(maxf-tmp,f);
 63             f=dfs(v,minn,t);
 64             e[i].f-=f;     //正向边 
 65             e[i^1].f+=f;    //反向边 
 66             //这里的^是很常用的,因为前向星加边是两条一起加的,所以一个标号是奇数,一个是偶数,所以^1一下可以得到另一条边,比如0^1 = 1,1 ^ 1 = 0, 2^1 = 3,3 ^1 = 2;
 67             tmp+=f;
 68         }
 69     }
 70     if(!tmp)level[u]=1000000000;
 71     return tmp;
 72 }
 73 
 74 void dinic(int s,int t)
 75 {
 76     while(bfs(s,t)){
 77         ans+=dfs(s,1000000000,t);
 78     }
 79 }
 80 
 81 int main()
 82 {
 83     scanf("%d%d",&n,&m);
 84     memset(head,-1,sizeof(head));
 85     for(int i=1;i<=m;i++)
 86     {
 87         int u,v,f;
 88         scanf("%d%d%d",&u,&v,&f);
 89         addedge(u,v,f);
 90     }
 91     
 92     dinic(1,n);
 93     printf("%d ",ans);
 94     fa=true;
 95     bfs(1,n);
 96     printf("%d\n%d",sum+1,w[0]);
 97     for(int i=1;i<w.size();i++)printf(" %d",w[i]);
 98     
 99     return 0;
100 } 
View Code

 

转载于:https://www.cnblogs.com/wzq--boke/p/8409667.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值