HDU3549 最大流 裸题

EK算法 时间复杂度o(n*m*m)  因为有反向边每次bfs时间为 n*m 每次删一条边 最多m次

 代码

 1 #include<iostream>
 2 #include<string.h>
 3 #include<vector>
 4 #include<stdio.h>
 5 #include<queue>
 6 using namespace std;
 7 const int maxn=2e5+10,inf=0x3f3f3f3f;
 8 typedef long long ll;
 9 struct edge
10 {
11     int from,to,c,f;
12     edge(int u,int v,int c,int f):from(u),to(v),c(c),f(f) {}
13 };
14 int n,m;
15 vector<edge> edges;
16 vector<int> g[maxn];
17 int a[maxn],p[maxn];
18 void init()
19 {
20     for(int i=0; i<=n; i++) g[i].clear();
21     edges.clear();
22 }
23 void addedge(int from,int to,int c)
24 {
25     edges.push_back(edge(from,to,c,0));
26     edges.push_back(edge(to,from,0,0));
27     int siz=edges.size();
28     g[from].push_back(siz-2);
29     g[to].push_back(siz-1);
30 }
31 ll maxflow(int s,int t)
32 {
33     ll flow=0;
34     while(1)
35     {
36         memset(a,0,sizeof(a));
37         queue<int> q;
38         q.push(s);
39         a[s]=inf;
40         while(!q.empty())
41         {
42             int x=q.front();
43             q.pop();
44             //  cout<<x<<" "<<g[x].size()<<endl;
45             for(int i=0; i<g[x].size(); i++)
46             {
47                 int u=g[x][i];
48                 edge &e=edges[u];
49                 //cout<<e.from<<" "<<e.to<<endl;
50                 if(!a[e.to]&&e.c>e.f)
51                 {
52                     p[e.to]=u; //存边
53                     a[e.to]=min(a[x],e.c-e.f);
54                     q.push(e.to);
55                 }
56             }
57             if(a[t])break;
58         }
59         // cout<<a[t]<<endl;                   //a[t]为一次增广值
60         if(!a[t]) break;
61         for(int u=t; u!=s; u=edges[p[u]].from)//流量修改
62         {
63             edges[p[u]].f+=a[t];
64             edges[p[u]^1].f-=a[t];
65         }
66         flow+=(ll)a[t];
67     }
68     return flow;
69 }
70 int main()
71 {
72     int t,u,v,c,f,kase=1;
73     cin>>t;
74     while(t--)
75     {
76         cin>>n>>m;
77         init();
78         for(int i=0; i<m; i++)
79         {
80             cin>>u>>v>>c;
81             addedge(u-1,v-1,c);
82         }
83         printf("Case %d: %d\n",kase++,maxflow(0,n-1));
84         //cout<<maxflow(0,n-1)<<endl;
85     }
86 }

Dinic  时间复杂度o(n*n*m)最多计算n-1次阻塞流 每次n*m  很松的上界

代码

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int maxn=1e3+20,mod=1e9+7,inf=0x3f3f3f3f;
 4 typedef long long ll;
 5 struct edge
 6 {
 7     int from,to,c,f;
 8     edge(int u,int v,int c,int f):from(u),to(v),c(c),f(f) {}
 9 };
10 int n,m;
11 vector<edge> edges;
12 vector<int> g[maxn];
13 int d[maxn];//从起点到i的距离
14 int cur[maxn];//当前弧下标
15 void init()
16 {
17     for(int i=0; i<=n; i++) g[i].clear();
18     edges.clear();
19 }
20 void addedge(int from,int to,int c) //加边 支持重边
21 {
22     edges.push_back(edge(from,to,c,0));
23     edges.push_back(edge(to,from,0,0));
24     int siz=edges.size();
25     g[from].push_back(siz-2);
26     g[to].push_back(siz-1);
27 }
28 int bfs(int s,int t) //构造一次层次图
29 {
30     memset(d,-1,sizeof(d));
31     queue<int> q;
32     q.push(s);
33     d[s]=0;
34     while(!q.empty())
35     {
36         int x=q.front();q.pop();
37         for(int i=0;i<g[x].size();i++)
38         {
39             edge &e=edges[g[x][i]];
40             if(d[e.to]<0&&e.f<e.c) //d[e.to]=-1表示没访问过
41             {
42                 d[e.to]=d[x]+1;
43                 q.push(e.to);
44             }
45         }
46     }
47     return d[t];
48 }
49 int dfs(int x,int a,int t) // a表示x点能接收的量
50 {
51     if(x==t||a==0)return a;
52     int flow=0,f;//flow总的增量 f一条增广路的增量
53     for(int &i=cur[x];i<g[x].size();i++)//cur[i] &引用修改其值 从上次考虑的弧
54     {
55         edge &e=edges[g[x][i]];
56         if(d[x]+1==d[e.to]&&(f=dfs(e.to,min(a,e.c-e.f),t))>0)    //按照层次图增广 满足容量限制
57         {
58             e.f+=f;
59             edges[g[x][i]^1].f-=f;  //修改流量
60             flow+=f;
61             a-=f;
62             if(a==0) break;
63         }
64     }
65     return flow;
66 }
67 int maxflow(int s,int t)
68 {
69     int flow=0;
70     while(bfs(s,t)!=-1) //等于-1代表构造层次图失败 结束
71     {
72         memset(cur,0,sizeof(cur));
73         flow+=dfs(s,inf,t);
74     }
75     return flow;
76 }
77 int main()
78 {
79     int t,kase=1;
80     scanf("%d",&t);
81     while(t--)
82     {
83         scanf("%d%d",&n,&m);
84         init();
85         int u,v,c,f;
86         for(int i=0;i<m;i++)
87         {
88             scanf("%d%d%d",&u,&v,&c);
89             addedge(u,v,c);
90         }
91         printf("Case %d: %d\n",kase++,maxflow(1,n));
92     }
93 }

 ISAP  gap优化版  性能比dinic 好一点

  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 const int maxn=1e3+20,mod=1e9+7,inf=0x3f3f3f3f;
  4 typedef long long ll;
  5 struct Edge
  6 {
  7     int from,to,cap,flow;
  8     Edge(int u,int v,int c,int f):from(u),to(v),cap(c),flow(f) {}
  9 };
 10 int n,m;
 11 vector<Edge>edges;
 12 vector<int>G[maxn];
 13 int vis[maxn];
 14 int d[maxn],cur[maxn];
 15 int p[maxn],num[maxn];//比Dinic算法多了这两个数组,p数组标记父亲结点,num数组标记距离d[i]存在几个
 16 void init()
 17 {
 18     for(int i=0; i<=n; i++) G[i].clear();
 19     edges.clear();
 20     memset(d,-1,sizeof(d));
 21 }
 22 void addedge(int from,int to,int cap)
 23 {
 24     edges.push_back(Edge(from,to,cap,0));
 25     edges.push_back(Edge(to,from,0,0));
 26     int m=edges.size();
 27     G[from].push_back(m-2);
 28     G[to].push_back(m-1);
 29 }
 30 int Augumemt(int s,int t)
 31 {
 32     int x=t,a=inf;
 33     while(x!=s)//找最小的残量值
 34     {
 35         Edge&e=edges[p[x]];
 36         a=min(a,e.cap-e.flow);
 37         x=edges[p[x]].from;
 38     }
 39     x=t;
 40     while(x!=s)//增广
 41     {
 42         edges[p[x]].flow+=a;
 43         edges[p[x]^1].flow-=a;//更新反向边。
 44         x=edges[p[x]].from;
 45     }
 46     return a;
 47 }
 48 void bfs(int t)//逆向进行bfs
 49 {
 50     memset(vis,0,sizeof(vis));
 51     queue<int>q;
 52     q.push(t);
 53     d[t]=0;
 54     vis[t]=1;
 55     while(!q.empty())
 56     {
 57         int x=q.front();
 58         q.pop();
 59         int len=G[x].size();
 60         for(int i=0; i<len; i++)
 61         {
 62             Edge&e=edges[G[x][i]];
 63             if(!vis[e.from]&&e.cap>e.flow)
 64             {
 65                 vis[e.from]=1;
 66                 d[e.from]=d[x]+1;
 67                 q.push(e.from);
 68             }
 69         }
 70     }
 71 }
 72 
 73 int Maxflow(int s,int t)//根据情况前进或者后退,走到汇点时增广
 74 {
 75     int flow=0;
 76     bfs(t);
 77     memset(num,0,sizeof(num));
 78     for(int i=0; i<=n; i++)
 79         num[d[i]]++;
 80     int x=s;
 81     memset(cur,0,sizeof(cur));
 82     while(d[s]<n)
 83     {
 84         if(x==t)//走到了汇点,进行增广
 85         {
 86             flow+=Augumemt(s,t);
 87             x=s;//增广后回到源点
 88         }
 89         int ok=0;
 90         for(int i=cur[x]; i<G[x].size(); i++)
 91         {
 92             Edge& e=edges[G[x][i]];
 93             if(e.cap>e.flow&&d[x]==d[e.to]+1)
 94             {
 95                 ok=1;
 96                 p[e.to]=G[x][i];//记录来的时候走的边,即父边
 97                 cur[x]=i;
 98                 x=e.to;//前进
 99                 break;
100             }
101         }
102         if(!ok)//走不动了,撤退
103         {
104             int m=n-1;//如果没有弧,那么m+1就是n,即d[i]=n
105             for(int i=0; i<G[x].size(); i++)
106             {
107                 Edge& e=edges[G[x][i]];
108                 if(e.cap>e.flow)
109                     m=min(m,d[e.to]);
110             }
111             if(--num[d[x]]==0)break;//如果走不动了,且这个距离值原来只有一个,那么s-t不连通,这就是所谓的“gap优化”
112             num[d[x]=m+1]++;
113             cur[x]=0;
114             if(x!=s)
115                 x=edges[p[x]].from;//退一步,沿着父边返回
116         }
117     }
118     return flow;
119 }
120 
121 int main()
122 {
123     int t,kase=1;
124     scanf("%d",&t);
125     while(t--)
126     {
127         init();
128         scanf("%d%d",&n,&m);
129         for(int i=0; i<m; i++)
130         {
131             int from,to,cap;
132             scanf("%d%d%d",&from,&to,&cap);
133             addedge(from,to,cap);
134         }
135         printf("Case %d: %d\n",kase++,Maxflow(1,n));
136     }
137     return 0;
138 }

ISAP算法 详解及其他版本参见https://blog.csdn.net/guhaiteng/article/details/52433239

转载于:https://www.cnblogs.com/stranger-/p/9343611.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值