POJ 1273 Drainage Ditches【最大流模版】

题意:现在有m个池塘(从1到m开始编号,1为源点,m为汇点),及n条有向水渠,给出这n条水渠所连接的点和所能流过的最大流量,求从源点到汇点能流过的最大流量

Dinic

 1 #include<iostream>
 2 #include<cstring>
 3 #include<algorithm>
 4 #include <cstdio>
 5 #include <queue>
 6 using namespace std;
 7 const int N = 202;
 8 const int INF = 0x3f3f3f3f;
 9 int m,n,tot;
10 int head[N],level[N];
11 struct node
12 {
13     int t,next,w;
14 }edge[N<<2];
15 
16 
17 void init()
18 {
19     tot=-1;
20     memset(head,-1, sizeof(head));
21 }
22 
23 void add(int s,int t,int w)
24 {
25     edge[++tot].t=t,edge[tot].w=w,edge[tot].next=head[s],head[s]=tot;
26     edge[++tot].t=s,edge[tot].w=0,edge[tot].next=head[t],head[t]=tot;
27 }
28 
29 bool bfs()
30 {
31     memset(level,0,sizeof(level));
32     queue<int> q;
33     while(!q.empty())q.pop();
34     q.push(1);
35     level[1]=1;
36     while(q.size())
37     {
38         int u=q.front();q.pop();
39         for(int i=head[u];i!=-1;i=edge[i].next)
40         {
41             if(edge[i].w>0&&level[edge[i].t]==0)
42             {
43                 q.push(edge[i].t);
44                 level[edge[i].t]=level[u]+1;
45             }
46             if(level[m]!=0)return 1;
47         }
48     }
49     return 0;
50 }
51 
52 int dfs(int s,int t, int flow)
53 {
54     if(s==t)return flow;
55     for(int i=head[s];i!=-1;i=edge[i].next)
56     {
57         if(edge[i].w>0&&level[edge[i].t]==level[s]+1)
58         {
59             int k = dfs(edge[i].t,t,min(flow,edge[i].w));
60             if(k>0)
61             {
62                 edge[i].w-=k;
63                 edge[i^1].w+=k;
64                 return k;
65             }
66         }
67     }
68     return 0;
69 }
70 //
71 void dinic()
72 {
73     int flow=0;
74     while(bfs()) // 寻找最短增广路,分层图
75     {
76         int f=0;
77         while((f=dfs(1,m,INF))>0)flow+=f; // 在分层图上增广
78     }
79     cout<<flow<<endl;
80 }
81 int main()
82 {
83     while(~scanf("%d%d",&n,&m))
84     {
85         init();
86         while(n--)
87         {
88             int a,b,c;
89             scanf("%d%d%d",&a,&b,&c);
90             add(a,b,c);
91         }
92         dinic();
93     }
94     return 0;
95 }

建图的另一种方法,上面有两种邻接表的方法,一种是单纯用数组模拟,可以运用异或操作反向边;另一个是vector模拟,反向边做特别记录

 1 struct edge
 2 {
 3     int to,cap,rev;// 反向边
 4 };
 5 vector<edge> g[maxn];
 6 int level[maxn];
 7 
 8 void add_edge(int from,int to,int cap)
 9 {
10     //最后一个元素是反向边的索引,便于快速查找
11     g[from].push_back((edge){to,cap,g[to].size()}); 
12     g[to].push_back((edge){from,0,g[from].size()-1});
13 }

Ford_Fulkerson

猜你喜欢

转载自www.cnblogs.com/demian/p/9219318.html