网络流入门
poj1459
http://poj.org/problem?id=1459
电站由组成consumer,dispatcher,power station,问最大传输电流
题意故意弄得非常复杂,其实就是多源多汇点,那么只要设置一个s往所有的源连,把所有的汇连到一个t再dinic就行了。
值得注意的两点:1.init必须在所有的开头调用 2.这题的(1,2)20这种读入比较奇葩,只要先读入buf,然后sscanf("(%d,%d)%d")就可以了
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<cstdio> #include<cstring> #include<cstdlib> #include<vector> #include<algorithm> #include<functional> #include<iostream> #include<cmath> #include<string> #include<cctype> #include<stack> #include<queue> #include<set> #include<map> #include<ctime> using namespace std; #define For(i,k,n) for(int i=k;i<=n;i++) #define ForD(i,k,n) for(int i=n;i>=k;i--) #define Lson (x<<1) #define Rson ((x<<1)+1) #define MEM(a) memset(a,0,sizeof(a)); #define NEG(a) memset(a,-1,sizeof(a)); #define INF 0x3f3f3f3f #define LLINF 0x3f3f3f3f3f3f3f3f #define ll long long #define print(b,a) cout<<b<<"="<<a<<endl; #define printbin(b,a){int tmp=a;string s;do{s+=tmp%2+'0';tmp/=2;}while(tmp);reverse(s.begin(),s.end());cout<<"bin "<<b<<"="<<s<<endl;} #define printarr(i,a,f,b) {For(i,f,b) printf("%d ",a[i]); printf("\n");} #define MAXN 20000 #define MAXM 200000 struct Node { int from,to,next; int cap; }edge[MAXM]; int tol; int dep[MAXN];//dep为点的层次 int head[MAXN]; void init() { tol=0; memset(head,-1,sizeof(head)); } void addedge(int u,int v,int w)//第一条变下标必须为偶数 { edge[tol].from=u; edge[tol].to=v; edge[tol].cap=w; edge[tol].next=head[u]; head[u]=tol++; edge[tol].from=v; edge[tol].to=u; edge[tol].cap=0; edge[tol].next=head[v]; head[v]=tol++; //printf("u=%d v=%d w=%d\n",u,v,w); } int BFS(int start,int end) { int que[MAXN]; int front,rear; front=rear=0; memset(dep,-1,sizeof(dep)); que[rear++]=start; dep[start]=0; while(front!=rear) { int u=que[front++]; if(front==MAXN)front=0; for(int i=head[u];i!=-1;i=edge[i].next) { int v=edge[i].to; if(edge[i].cap>0&&dep[v]==-1) { dep[v]=dep[u]+1; que[rear++]=v; if(rear>=MAXN)rear=0; if(v==end)return 1; } } } return 0; } int dinic(int start,int end) { int res=0; int top; int stack[MAXN];//stack为栈,存储当前增广路 int cur[MAXN];//存储当前点的后继 while(BFS(start,end)) { //printf("res=%d\n",res); memcpy(cur,head,sizeof(head)); int u=start; top=0; while(1) { if(u==end) { int min=INF; int loc; for(int i=0;i<top;i++) if(min>edge[stack[i]].cap) { min=edge[stack[i]].cap; loc=i; } for(int i=0;i<top;i++) { edge[stack[i]].cap-=min; edge[stack[i]^1].cap+=min; } res+=min; top=loc; u=edge[stack[top]].from; } for(int i=cur[u];i!=-1;cur[u]=i=edge[i].next) if(edge[i].cap!=0&&dep[u]+1==dep[edge[i].to]) break; if(cur[u]!=-1) { stack[top++]=cur[u]; u=edge[cur[u]].to; } else { if(top==0)break; dep[u]=-1; u=edge[stack[--top]].from; } } } return res; } char buf[MAXN]; int main() { //freopen("in.txt","r",stdin); int n,np,nc,m; int u,v,cap; while(scanf("%d%d%d%d",&n,&np,&nc,&m)==4) { init(); For(i,0,m-1) { scanf("%s",buf); sscanf(buf,"(%d,%d)%d",&u,&v,&cap); u++;v++; addedge(u,v,cap); } For(i,0,np-1) { scanf("%s",buf); sscanf(buf,"(%d)%d",&u,&cap); u++; addedge(0,u,cap); } For(i,0,nc-1) { scanf("%s",buf); sscanf(buf,"(%d)%d",&u,&cap); u++; addedge(u,n+1,cap); } printf("%d\n",dinic(0,n+1)); } return 0; }
poj1698
http://poj.org/problem?id=1698
alice要拍n部电影,每部电影要至少拍di天,必须要wi天内拍完,给出每个电影能在一个礼拜那些天拍。问能否拍完
s往电影连di,电影往所有能拍的天连1,所有的天往t连1,最大流
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<cstdio> #include<cstring> #include<cstdlib> #include<vector> #include<algorithm> #include<functional> #include<iostream> #include<cmath> #include<string> #include<cctype> #include<stack> #include<queue> #include<set> #include<map> #include<ctime> using namespace std; #define For(i,k,n) for(int i=k;i<=n;i++) #define ForD(i,k,n) for(int i=n;i>=k;i--) #define Lson (x<<1) #define Rson ((x<<1)+1) #define MEM(a) memset(a,0,sizeof(a)); #define NEG(a) memset(a,-1,sizeof(a)); #define INF 0x3f3f3f3f #define LLINF 0x3f3f3f3f3f3f3f3f #define ll long long #define print(b,a) cout<<b<<"="<<a<<endl; #define printbin(b,a){int tmp=a;string s;do{s+=tmp%2+'0';tmp/=2;}while(tmp);reverse(s.begin(),s.end());cout<<"bin "<<b<<"="<<s<<endl;} #define printarr(i,a,f,b) {For(i,f,b) printf("%d ",a[i]); printf("\n");} #define MAXN 20000 #define MAXM 200000 struct Node { int from,to,next; int cap; }edge[MAXM]; int tol; int dep[MAXN];//dep为点的层次 int head[MAXN]; int a[MAXN][10]; void init() { tol=0; memset(head,-1,sizeof(head)); } void addedge(int u,int v,int w)//第一条变下标必须为偶数 { edge[tol].from=u; edge[tol].to=v; edge[tol].cap=w; edge[tol].next=head[u]; head[u]=tol++; edge[tol].from=v; edge[tol].to=u; edge[tol].cap=0; edge[tol].next=head[v]; head[v]=tol++; //printf("u=%d v=%d w=%d\n",u,v,w); } int BFS(int start,int end) { int que[MAXN]; int front,rear; front=rear=0; memset(dep,-1,sizeof(dep)); que[rear++]=start; dep[start]=0; while(front!=rear) { int u=que[front++]; if(front==MAXN)front=0; for(int i=head[u];i!=-1;i=edge[i].next) { int v=edge[i].to; if(edge[i].cap>0&&dep[v]==-1) { dep[v]=dep[u]+1; que[rear++]=v; if(rear>=MAXN)rear=0; if(v==end)return 1; } } } return 0; } int dinic(int start,int end) { int res=0; int top; int stack[MAXN]; int cur[MAXN]; while(BFS(start,end)) { memcpy(cur,head,sizeof(head)); int u=start; top=0; while(1) { if(u==end) { int min=INF; int loc; for(int i=0;i<top;i++) if(min>edge[stack[i]].cap) { min=edge[stack[i]].cap; loc=i; } for(int i=0;i<top;i++) { edge[stack[i]].cap-=min; edge[stack[i]^1].cap+=min; } res+=min; top=loc; u=edge[stack[top]].from; } for(int i=cur[u];i!=-1;cur[u]=i=edge[i].next) if(edge[i].cap!=0&&dep[u]+1==dep[edge[i].to]) break; if(cur[u]!=-1) { stack[top++]=cur[u]; u=edge[cur[u]].to; } else { if(top==0)break; dep[u]=-1; u=edge[stack[--top]].from; } } } return res; } char buf[MAXN]; int main() { //freopen("in.txt","r",stdin); int t; scanf("%d",&t); int flg=0; while(t--) { init(); int n,sum=0; flg=0; scanf("%d",&n); For(i,1,n) { For(j,1,7) scanf("%d",&a[i][j]); int D,W; scanf("%d %d",&D,&W); addedge(0,i,D); sum+=D; if(flg<W) flg=W; For(k,0,W-1) For(j,1,7) if(a[i][j]) addedge(i,7*k+j+n,1); } int T=n+7*flg+1; For(i,0,flg-1) For(j,1,7) addedge(7*i+n+j,T,1); int ans=dinic(0,T); if(ans==sum) printf("Yes\n"); else printf("No\n"); } return 0; }
poj2112
http://poj.org/problem?id=2112
有K台挤奶机(编号1~K),C头奶牛(编号K+1~K+C),给出各点之间距离。现在要让C头奶牛到挤奶机去挤奶,每台挤奶机只能处理M头奶牛,求使所走路程最远的奶牛的路程最短的方案。
非常简单,二分dinic
值得注意的只是二分的时候r设置大一点
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<cstdio> #include<cstring> #include<cstdlib> #include<vector> #include<algorithm> #include<functional> #include<iostream> #include<cmath> #include<string> #include<cctype> #include<stack> #include<queue> #include<set> #include<map> #include<ctime> using namespace std; #define For(i,k,n) for(int i=k;i<=n;i++) #define ForD(i,k,n) for(int i=n;i>=k;i--) #define Lson (x<<1) #define Rson ((x<<1)+1) #define MEM(a) memset(a,0,sizeof(a)); #define NEG(a) memset(a,-1,sizeof(a)); #define FILL(a) memset(a,0x3f,sizeof(a)); #define INF 0x3f3f3f3f #define LLINF 0x3f3f3f3f3f3f3f3f #define ll long long #define print(b,a) cout<<b<<"="<<a<<endl; #define printbin(b,a){int tmp=a;string s;do{s+=tmp%2+'0';tmp/=2;}while(tmp);reverse(s.begin(),s.end());cout<<"bin "<<b<<"="<<s<<endl;} #define printarr(i,a,f,b) {For(i,f,b) printf("%d ",a[i]); printf("\n");} #define MAXN 400000 struct Node { int from,to,next; int cap; }edge[MAXN]; int tol; int dep[MAXN];//dep为点的层次 int head[MAXN]; void init() { tol=0; memset(head,-1,sizeof(head)); } void addedge(int u,int v,int w)//第一条变下标必须为偶数 { edge[tol].from=u; edge[tol].to=v; edge[tol].cap=w; edge[tol].next=head[u]; head[u]=tol++; edge[tol].from=v; edge[tol].to=u; edge[tol].cap=0; edge[tol].next=head[v]; head[v]=tol++; //printf("u=%d v=%d w=%d\n",u,v,w); } int BFS(int start,int end) { int que[MAXN]; int front,rear; front=rear=0; memset(dep,-1,sizeof(dep)); que[rear++]=start; dep[start]=0; while(front!=rear) { int u=que[front++]; if(front==MAXN)front=0; for(int i=head[u];i!=-1;i=edge[i].next) { int v=edge[i].to; if(edge[i].cap>0&&dep[v]==-1) { dep[v]=dep[u]+1; que[rear++]=v; if(rear>=MAXN)rear=0; if(v==end)return 1; } } } return 0; } int dinic(int start,int end) { int res=0; int top; int stack[MAXN]; int cur[MAXN]; while(BFS(start,end)) { memcpy(cur,head,sizeof(head)); int u=start; top=0; while(1) { if(u==end) { int min=INF; int loc; for(int i=0;i<top;i++) if(min>edge[stack[i]].cap) { min=edge[stack[i]].cap; loc=i; } for(int i=0;i<top;i++) { edge[stack[i]].cap-=min; edge[stack[i]^1].cap+=min; } res+=min; top=loc; u=edge[stack[top]].from; } for(int i=cur[u];i!=-1;cur[u]=i=edge[i].next) if(edge[i].cap!=0&&dep[u]+1==dep[edge[i].to]) break; if(cur[u]!=-1) { stack[top++]=cur[u]; u=edge[cur[u]].to; } else { if(top==0)break; dep[u]=-1; u=edge[stack[--top]].from; } } } return res; } int d[250][250]; int K,C,M; void floyd() { For(k,1,K+C) For(i,1,K+C) For(j,1,K+C) d[i][j]=min(d[i][j],d[i][k]+d[k][j]); // For(i,1,K+C) For(j,1,K+C) printf("d[%d][%d]=%d\n",i,j,d[i][j] ); } int main() { //freopen("in.txt","r",stdin); scanf("%d%d%d",&K,&C,&M); For(i,1,K+C) For(j,1,K+C) { scanf("%d",&d[i][j]); if(d[i][j]==0) d[i][j]=INF; } floyd(); int l=1,r=9999999,ans=1; while(l<=r) { int m=(l+r)/2; //printf("m=%d\n",m); init(); For(i,1,K) addedge(0,i,M); For(i,K+1,K+C) addedge(i,K+C+1,1); For(i,1,K) For(j,K+1,K+C) if(m>=d[i][j]) addedge(i,j,1); int ret=dinic(0,K+C+1); //printf("ret=%d\n",ret); if(ret==C) { r=m-1; ans=m; } else { l=m+1; } } printf("%d\n",ans); return 0; }
poj2455
蜜汁无限tle,暂时搁置