最大流
- 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 }