網絡流算法筆記
阿新 • • 發佈:2018-08-23
cond ring for 最大 con () sstream head getch
【例題】
1.POJ Drainage Ditches 【最大流EK算法模板】
#include<cstdio> #include<string> #include<cstdlib> #include<cmath> #include<iostream> #include<cstring> #include<set> #include<queue> #include<algorithm> #include<vector> #include<map> #include<cctype> #include<stack> #include<sstream> #include<list> #include<assert.h> #include<bitset> #include<numeric> #define debug() puts("++++") #define gcd(a,b) __gcd(a,b) #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 #define fi first #define se second #define pb push_back #define sqr(x) ((x)*(x)) #define ms(a,b) memset(a,b,sizeof(a)) #define sz size() #define be begin() #define pu push_up #define pd push_down #define cl clear() #define lowbit(x) -x&x #define all 1,n,1 #define mod(x) ((x)%M) #define pi acos(-1.0) #define rep(i,x,n) for(int i=(x); i<(n); i++) using namespace std; typedef long long LL; typedef unsigned long long ULL; typedef pair<int,int> P; const int INF = 1<<30; const int maxn = 1e3; const double eps = 1e-8; const int dx[] = {-1,1,0,0,1,1,-1,-1}; const int dy[] = {0,0,1,-1,1,-1,1,-1}; int dir[2]={-1,1}; const int mon[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; const int monn[] = {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; int s,t,n,m; inline int read() { int x=0; char c=getchar(); while(c>'9'||c<'0')c=getchar(); while(c>='0'&&c<='9')x=x*10+c-'0',c=getchar(); return x; } int head[maxn],tot=1; void init() { ms(head,-1); tot=1; } struct Pre { int v,edge;//該點的前一個點(從起點過來) 與該點相連的邊(靠近起點的) }pre[maxn]; struct node { int v,w,nxt; }e[maxn]; void add(int u,int v,int w) { e[++tot].v=v; e[tot].w=w; e[tot].nxt=head[u]; head[u]=tot; } int vis[maxn]; inline bool bfs() { queue<int> q; ms(vis,0);ms(pre,-1); vis[s]=1; q.push(s); while(!q.empty()) { int u=q.front(); q.pop(); for(int i=head[u]; i!=-1; i=e[i].nxt) { int v=e[i].v; if(!vis[v]&&e[i].w) { pre[v].v=u; pre[v].edge=i; if(v==t) return 1; vis[v]=1; q.push(v); } } } return 0; } int ek() { int ans=0; while(bfs()) { int mi=INF; for(int i=t; i!=s; i=pre[i].v)//每次只能增加增廣路上最小的邊的權值 { mi = min(mi,e[pre[i].edge].w); } for(int i=t; i!=s; i=pre[i].v) { e[ pre[i].edge ].w -= mi; e[ pre[i].edge^1 ].w += mi; } ans += mi; } return ans; } int main() { while(~scanf("%d%d",&m,&n)) { init(); s=1,t=n; int u,v,w; for(int i=1;i<=m;i++) u=read(),v=read(),w=read(),add(u,v,w),add(v,u,0); printf("%d\n",ek()); } } /* 【題意】 【類型】最大流EK算法模板 【分析】https://www.luogu.org/blog/ONE-PIECE/wang-lao-liu-di-zong-jie 【時間復雜度&&優化】O(nm^2)(n為點數,m為邊數) 【trick】 【數據】 */
2.洛谷 P3376 【模板】網絡最大流
#include<cstdio> #include<string> #include<cstdlib> #include<cmath> #include<iostream> #include<cstring> #include<set> #include<queue> #include<algorithm> #include<vector> #include<map> #include<cctype> #include<stack> #include<sstream> #include<list> #include<assert.h> #include<bitset> #include<numeric> #define debug() puts("++++") #define gcd(a,b) __gcd(a,b) #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 #define fi first #define se second #define pb push_back #define sqr(x) ((x)*(x)) #define ms(a,b) memset(a,b,sizeof(a)) #define sz size() #define be begin() #define pu push_up #define pd push_down #define cl clear() #define lowbit(x) -x&x #define all 1,n,1 #define mod(x) ((x)%M) #define pi acos(-1.0) #define rep(i,x,n) for(int i=(x); i<(n); i++) using namespace std; typedef long long LL; typedef unsigned long long ULL; typedef pair<int,int> P; const int INF = 1<<30; const int maxn = 5e5+10; const double eps = 1e-8; const int dx[] = {-1,1,0,0,1,1,-1,-1}; const int dy[] = {0,0,1,-1,1,-1,1,-1}; int dir[2]={-1,1}; const int mon[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; const int monn[] = {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; int s,t,n,m; inline int read() { int x=0; char c=getchar(); while(c>'9'||c<'0')c=getchar(); while(c>='0'&&c<='9')x=x*10+c-'0',c=getchar(); return x; } int head[maxn],tot=1; void init() { ms(head,-1); tot=1; } struct Pre { int v,edge;//該點的前一個點(從起點過來) 與該點相連的邊(靠近起點的) }pre[maxn]; struct node { int v,w,nxt; }e[maxn]; void add(int u,int v,int w) { e[++tot].v=v; e[tot].w=w; e[tot].nxt=head[u]; head[u]=tot; } int inque[maxn]; inline bool bfs() { queue<int> q; ms(inque,0);ms(pre,-1); inque[s]=1; q.push(s); while(!q.empty()) { int u=q.front(); q.pop(); for(int i=head[u]; i!=-1; i=e[i].nxt) { int v=e[i].v; if(!inque[v]&&e[i].w) { pre[v].v=u; pre[v].edge=i; if(v==t) return 1; inque[v]=1; q.push(v); } } } return 0; } int ek() { int ans=0; while(bfs()) { int mi=INF; for(int i=t; i!=s; i=pre[i].v)//每次只能增加增廣路上最小的邊的權值 { mi = min(mi,e[pre[i].edge].w); } for(int i=t; i!=s; i=pre[i].v) { e[ pre[i].edge ].w -= mi; e[ pre[i].edge^1 ].w += mi; } ans += mi; } return ans; } int main() { init(); n=read(), m=read(), s=read(), t=read(); int u,v,w; for(int i=1;i<=m;i++) u=read(),v=read(),w=read(),add(u,v,w),add(v,u,0); printf("%d\n",ek()); } /* 4 5 4 3 4 2 30 4 3 20 2 3 20 2 1 30 1 3 40 【題意】 【類型】 【分析】 【時間復雜度&&優化】 【trick】 【數據】 */
3.HDU 3549 Flow Problem
#include<cstdio> #include<string> #include<cstdlib> #include<cmath> #include<iostream> #include<cstring> #include<set> #include<queue> #include<algorithm> #include<vector> #include<map> #include<cctype> #include<stack> #include<sstream> #include<list> #include<assert.h> #include<bitset> #include<numeric> #define debug() puts("++++") #define gcd(a,b) __gcd(a,b) #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 #define fi first #define se second #define pb push_back #define sqr(x) ((x)*(x)) #define ms(a,b) memset(a,b,sizeof(a)) #define sz size() #define be begin() #define pu push_up #define pd push_down #define cl clear() #define lowbit(x) -x&x #define all 1,n,1 #define mod(x) ((x)%M) #define pi acos(-1.0) #define rep(i,x,n) for(int i=(x); i<(n); i++) using namespace std; typedef long long LL; typedef unsigned long long ULL; typedef pair<int,int> P; const int INF = 1<<30; const int maxn = 2e3+3; const double eps = 1e-8; const int dx[] = {-1,1,0,0,1,1,-1,-1}; const int dy[] = {0,0,1,-1,1,-1,1,-1}; int dir[2]={-1,1}; const int mon[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; const int monn[] = {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; int s,t,n,m; inline int read() { int x=0; char c=getchar(); while(c>'9'||c<'0')c=getchar(); while(c>='0'&&c<='9')x=x*10+c-'0',c=getchar(); return x; } int head[maxn],tot=1; void init() { ms(head,-1); tot=1; } struct Pre { int v,edge;//該點的前一個點(從起點過來) 與該點相連的邊(靠近起點的) }pre[maxn]; struct node { int v,w,nxt; }e[maxn]; void add(int u,int v,int w) { e[++tot].v=v; e[tot].w=w; e[tot].nxt=head[u]; head[u]=tot; } int vis[maxn]; inline bool bfs() { queue<int> q; ms(vis,0);ms(pre,-1); vis[s]=1; q.push(s); while(!q.empty()) { int u=q.front(); q.pop(); if(u==t) return 1; for(int i=head[u]; i!=-1; i=e[i].nxt) { int v=e[i].v; if(!vis[v]&&e[i].w) { pre[v].v=u; pre[v].edge=i; vis[v]=1; q.push(v); } } } return 0; } int ek() { int ans=0; while(bfs()) { int mi=INF; for(int i=t; i!=s; i=pre[i].v)//每次只能增加增廣路上最小的邊的權值 { mi = min(mi,e[pre[i].edge].w); } for(int i=t; i!=s; i=pre[i].v) { e[ pre[i].edge ].w -= mi; e[ pre[i].edge^1 ].w += mi; } ans += mi; } return ans; } int main() { int T,ca=1; scanf("%d",&T); while(T--) { scanf("%d%d",&n,&m); init(); s=1,t=n; int u,v,w; for(int i=1;i<=m;i++) { scanf("%d%d%d",&u,&v,&w); add(u,v,w); add(v,u,0); } printf("Case %d: %d\n",ca++,ek()); } } /* 【題意】 【類型】最大流EK算法模板 【分析】 【時間復雜度&&優化】O(nm^2)(n為點數,m為邊數) 【trick】 【數據】 */
網絡流算法筆記