模板最大流(邻接表实现+炸点优化+Dinic算法+当前弧优化)

最大流

  • Time Limit: 60000/30000 MS (Java/Others)     Memory Limit: 562144/562144 K (Java/Others)
  • Total Submission(s): 22     Accepted Submission(s): 10
Description

这是一道模板题。

给定 n 个点,m 条边,给定每条边的容量,求从点 s 到点 t 的最大流。

Input

第一行四个整数 n, m, s, t 。

接下来的 m 行,每行三个整数 u, v, c 表示 u 到 v ,流量为 c 的一条边。

1 ⩽ n ⩽ 106 ,1 ⩽ m ⩽ 4×106 , 0 ⩽ c ⩽ 231-1

Output

输出点 s 到点 t 的最大流。

Sample Input

7 14 1 7
1 2 5
1 3 6
1 4 5
2 3 2
2 5 3
3 2 2
3 4 3
3 5 3
3 6 7
4 6 5
5 6 1
6 5 1
5 7 8
6 7 7

Sample Output

14

这虽说明说是一道最大流模板题,可实现起来不是直接能套用模板能实现的了,n为1e6了二维数组定放不下只能考邻接表。
  1 #include<iostream>
  2 #include<cstdio>
  3 #include<queue>
  4 #include<cstring>
  5 #define maxx 1000005
  6 #define inf 0x3f3f3f3f
  7 using namespace std;
  8 int diss[maxx],nowing[maxx];//diss[]表示由出发点到i的层次距离///nowing表当前弧
  9 int n,m,s,e;
 10 queue<int> q;
 11 struct Node{
 12 int to;
 13 int cap;
 14 int rev;
 15 };vector<Node> ma[maxx];
 16 struct Dinic
 17 {
 18 
 19 inline void read(int &x){
 20     char ch;
 21     bool flag=false;
 22     for (ch=getchar();!isdigit(ch);ch=getchar())if (ch=='-') flag=true;
 23     for (x=0;isdigit(ch);x=x*10+ch-'0',ch=getchar());
 24     x=flag?-x:x;
 25 }
 26 inline void write(int x){
 27     static const int maxlen=100;
 28     static char s[maxlen];
 29         if (x<0) {   putchar('-'); x=-x;}
 30     if(!x){ putchar('0'); return; }
 31     int len=0; for(;x;x/=10) s[len++]=x % 10+'0';
 32     for(int i=len-1;i>=0;--i) putchar(s[i]);
 33 }
 34 void bfs(int s)///通过BFS计算从源点出发的距离标号{
 35 fill(diss,diss+maxx,-1);
 36 diss[s]=0;
 37 q.push(s);
 38 int now;
 39 while(!q.empty()){
 40     now=q.front();
 41     q.pop();
 42     for(int i=0;i<ma[now].size();i++)
 43     {
 44         Node &v=ma[now][i];
 45         if(v.cap>0&&diss[v.to]==-1){
 46             diss[v.to]=diss[now]+1;
 47             q.push(v.to);
 48         }
 49     }
 50 }
 51 }
 52 /*int dfs(int v,int t,int a){
 53 if(v==t)
 54     return a;
 55     int flow=0;
 56     int d=0;
 57 for(int &i=nowing[v];i<ma[v].size();i++){
 58     Node &e=ma[v][i];
 59     if(e.cap>0&&diss[v]<diss[e.to]){
 60          d=dfs(e.to,t,min(a,e.cap));
 61         if(d>0){
 62             e.cap-=d;
 63             ma[e.to][e.rev].cap+=d;
 64             flow += d;
 65                 a -= d;
 66                 if(a==0) break;
 67         }
 68 
 69 }    } if(!flow) diss[v] = -1;
 70 else
 71     return flow;
 72 
 73 } */int dfs(int x,int a)//寻找增扩路
 74     {
 75         if(x==e || a==0)return a;
 76         int flow=0,f;//flow用来记录从x到t的最小残量
 77         for(int &i=nowing[x]; i<ma[x].size(); i++)
 78         {
 79             nowing[x]=i;//在此之前其他边已经淘汰
 80            Node &e=ma[x][i];
 81             if(diss[x]+1==diss[e.to] && (f=dfs( e.to,min(a,e.cap) ) )>0 )
 82             {
 83                e.cap-=f;
 84             ma[e.to][e.rev].cap+=f;
 85                 flow += f;
 86                 a -= f;
 87                 if(a==0) break;
 88             }
 89         }
 90         if(!flow) diss[x] = -1;///炸点优化,必不可少,证明不必要的点下一次就不用遍历
 91         return flow;
 92     }
 93 int mostflow(int s,int t){
 94 int sum=0;
 95 int dd;
 96 while(1){
 97     bfs(s);
 98     if(diss[t]==-1)
 99         return sum;
100     memset(nowing,0,sizeof(nowing));
101     while((dd=dfs(s,inf))>0){
102         sum+=dd;
103     }
104 }
105 }}MM;
106 int main(){
107 while(scanf("%d %d %d %d",&n,&m,&s,&e)!=EOF){
108     while(m--){
109             int a,b,c;
110         MM.read(a),MM.read(b),MM.read(c);
111     ma[a].push_back((Node){b,c,ma[b].size()});
112     ma[b].push_back((Node){a,0,ma[a].size()-1});
113     }
114     MM.write(MM.mostflow(s,e));
115     
116 }
117 }

猜你喜欢

转载自www.cnblogs.com/Yum20/p/9560395.html