一、.这么犀利的建图第一次见到,不解释。就用这个题写一下模板。
参考资料:http://imlazy.ycool.com/post.2059102.html
二、代码
1.(dinic+邻接表)
#include <iostream> #include<algorithm> #include<cstdio> #include<cstring> #include<string> using namespace std; //注意数据和内存的越界! //尤其是memset()上 #define N 1010 #define M 11000//double #define INF 100000000 int idx[N],cnt[N]; struct Node{ int u,v,next; int c; }; struct Graph { Node E[M]; int first[N]; int _V,_E,src,dest; int que[N],front,rear; int d[N]; void init(int n){ _V=n,_E=0; src=0;dest=_V-1; memset(first,-1,4*_V);//!!! } void build(int house,int cust) { init(cust+2); int i,j; for(i=1;i<=house;i++) { idx[i]=-1; scanf("%d",cnt+i); } int loop,num,cap; for(i=1;i<=cust;i++) { cap=0; scanf("%d",&num); for(j=0;j<num;j++) { scanf("%d",&loop); if(idx[loop]!=-1)add(idx[loop],i,INF); else cap+=cnt[loop],idx[loop]=i; } if(cap)add(src,i,cap); scanf("%d",&num); add(i,dest,num); } } void add(int u,int v,int c){ E[_E].u=u,E[_E].v=v,E[_E].c=c,E[_E].next=first[u],first[u]=_E,_E++; E[_E].u=v,E[_E].v=u,E[_E].c=0,E[_E].next=first[v],first[v]=_E,_E++;// } bool bfs() { memset(d,-1,4*_V);//!!! d[src]=0; front=rear=0; que[rear++]=src; while(front!=rear){ int u=que[front++]; for(int e=first[u];e!=-1;e=E[e].next){ int v=E[e].v; if(d[v]==-1&&E[e].c){ d[v]=d[u]+1; que[rear++]=v; } if(d[dest]!=-1)return true; } } return false; } int dfs(int u,int cap) { if(u==dest)return cap; int rest=cap,aug; for(int e=first[u];e!=-1&&rest;e=E[e].next){// int v=E[e].v,c=E[e].c; if(d[v]==d[u]+1&&c){ aug=dfs(v,rest>c?c:rest); rest-=aug; E[e].c-=aug; E[e^1].c+=aug; } } return cap-rest; } int dinic(){ int flow=0; while(bfs())flow+=dfs(src,INF); return flow; } void display(){ for(int i=0; i<_V; i++){ for(int e=first[i]; e!=-1; e=E[e].next){ int u=E[e].u,v=E[e].v; int c=E[e].c; cout<<u<<' '<<v<<' '; printf("%d\n",c); } } } }net; int main() { #ifndef ONLINE_JUDGE freopen("data.in", "r", stdin); #endif int n,m; cin>>n>>m; net.build(n,m); // net.display(); printf("%d\n",net.dinic()); return 0; }
#include <iostream> #include<cstdio> #include<cstring> #include<string> using namespace std; #define N 1010 #define INF 100000000 int idx[N]; int cnt[N]; struct Graph{ int map[N][N]; int _V,src,dest; int que[N],front,rear; int d[N]; void init(int n) { _V=n; src=0;dest=_V-1; for(int i=0;i<_V;i++) for(int j=0;j<_V;j++)map[i][j]=0;//!! } void build(int house,int cust) { init(cust+2); int i,j; for(i=1;i<=house;i++) { idx[i]=-1; scanf("%d",cnt+i); } int loop,num,cap; for(i=1;i<=cust;i++) { cap=0; scanf("%d",&num); for(j=0;j<num;j++) { scanf("%d",&loop); if(idx[loop]!=-1)map[idx[loop]][i]=INF; else cap+=cnt[loop],idx[loop]=i; } if(cap) map[src][i]=cap; scanf("%d",&num); map[i][dest]=num; } } bool bfs(){ memset(d,-1,4*_V);//!!! d[src]=0; front=rear=0; que[rear++]=src; while(front!=rear){ int u=que[front++]; for(int v=0;v<_V;v++){ if(d[v]==-1&&map[u][v]){ d[v]=d[u]+1; que[rear++]=v; } if(d[dest]!=-1)return true;// } } return false; } //函数的意义:求从u增广的最大流量,cp:当前可增广的最大流 int dfs(int u,int cap){ if(u==dest)return cap; int rest=cap,aug; for(int v=0;v<_V&&rest;v++){ if(d[v]==d[u]+1&&map[u][v]>0){ aug=dfs(v,rest<map[u][v]?rest:map[u][v]); rest-=aug; map[u][v]-=aug; map[v][u]+=aug; } } return cap-rest; } int dinic(){ int flow=0; while(bfs())flow+=dfs(src,INF); return flow; } void display() { for(int i=0;i<_V;i++) for(int j=0;j<_V;j++)cout<<i<<' '<<j<<' '<<map[i][j]<<endl; cout<<endl; } }net; int main() { #ifndef ONLINE_JUDGE freopen("data.in", "r", stdin); #endif int n,m; cin>>n>>m; net.build(n,m); // net.display(); printf("%d\n",net.dinic()); return 0; }
四、sap(邻接表)
一直都觉得从后往前标记不习惯,于是打算打算写从前往后标记的,但后来发现行不通!
才明白从后往前标记是没办法的办法呀!
#include <iostream> #include<algorithm> #include<cstdio> #include<cstring> #include<string> using namespace std; //注意数据和内存的越界! //尤其是memset()上 #define N 1010 #define M 11000//double #define INF 100000000 int idx[N],cnt[N]; struct Node{ int u,v,next; int c; }; struct Graph { Node E[M]; int first[N]; int _V,_E,src,dest; int d[N]; int num[N]; int pre[N],cur,next; void init(int n){ _V=n,_E=0; src=0;dest=_V-1; memset(first,-1,4*_V);//!!! } void build(int house,int cust) { init(cust+2); int i,j; for(i=1;i<=house;i++) { idx[i]=-1; scanf("%d",cnt+i); } int loop,num,cap; for(i=1;i<=cust;i++) { cap=0; scanf("%d",&num); for(j=0;j<num;j++) { scanf("%d",&loop); if(idx[loop]!=-1)add(idx[loop],i,INF); else cap+=cnt[loop],idx[loop]=i; } if(cap)add(src,i,cap); scanf("%d",&num); add(i,dest,num); } } void add(int u,int v,int c){ E[_E].u=u,E[_E].v=v,E[_E].c=c,E[_E].next=first[u],first[u]=_E,_E++; E[_E].u=v,E[_E].v=u,E[_E].c=0,E[_E].next=first[v],first[v]=_E,_E++;// } inline bool advance(){ for(int e=first[cur];e!=-1;e=E[e].next){ if(d[cur]==d[E[e].v]+1&&E[e].c){ pre[cur=E[e].v]=e; return true; } } return false; } inline int relable(){ int mini=_V-1; for(int e=first[cur];e!=-1;e=E[e].next)if(E[e].c&&d[E[e].v]<mini)mini=d[E[e].v]; return mini+1; } int sap(){ memset(d,-1,4*_V);//!!! memset(num,0,4*_V);// pre[src]=-1;//!!! int flow=0,aug; while(d[src]!=_V){ cur=src; while(cur!=dest){ if(advance())continue; int lable=relable(); num[d[cur]]--;num[d[cur]=lable]++; if( !num[d[cur]] || d[src]==_V )return flow; if(cur!=src)cur=E[pre[cur]].u;//满足可行弧定义 } aug=INF; int e=pre[dest],aug=INF; while(e!=-1)aug=aug<E[e].c?aug:E[e].c,e=pre[E[e].u]; flow+=aug;e=pre[dest]; while(e!=-1)E[e].c-=aug,E[e^1].c+=aug,e=pre[E[e].u]; } return flow; } }net; int main() { #ifndef ONLINE_JUDGE freopen("data.in", "r", stdin); #endif int n,m; cin>>n>>m; net.build(n,m); // net.display(); printf("%d\n",net.sap()); return 0; }
4.sap+邻接阵
#include <iostream> #include<cstdio> #include<cstring> #include<string> using namespace std; #define N 1010 #define INF 100000000 int idx[N]; int cnt[N]; struct Graph{ int map[N][N]; int _V,src,dest; int d[N]; int num[N]; int pre[N]; void init(int n){ _V=n; src=0;dest=_V-1; for(int i=0;i<_V;i++) for(int j=0;j<_V;j++)map[i][j]=0;//!! } void build(int house,int cust) { init(cust+2); int i,j; for(i=1;i<=house;i++) { idx[i]=-1; scanf("%d",cnt+i); } int loop,num,cap; for(i=1;i<=cust;i++) { cap=0; scanf("%d",&num); for(j=0;j<num;j++) { scanf("%d",&loop); if(idx[loop]!=-1)map[idx[loop]][i]=INF; else cap+=cnt[loop],idx[loop]=i; } if(cap) map[src][i]=cap; scanf("%d",&num); map[i][dest]=num; } } inline bool advance(int &u){ for(int v=0;v<_V;v++){ if(d[u]==d[v]+1&&map[u][v]){ pre[v]=u;u=v; return true; } } return false; } inline int relable(int u){ int mini=_V-1; for(int v=0;v<_V;v++) if(map[u][v]&&d[v]<mini) mini=d[v]; return mini+1; } int sap(){ int u,v,flow=0; memset(d,-1,4*_V);//bfs(); memset(num,0,4*_V);pre[src]=-1; while(true){ u=src; while(u!=dest){ if(advance(u))continue; int lable=relable(u); num[d[u]]--;num[d[u]=lable]++; if( !num[d[u]] || d[src]==_V )return flow; //!!源点标号不成功时,断层时到达最大流 if(u!=src)u=pre[u]; } v=u,u=pre[v];int aug=INF; while(u!=-1)aug=aug<map[u][v]?aug:map[u][v],v=u,u=pre[u]; flow+=aug;v=dest,u=pre[v]; while(u!=-1)map[u][v]-=aug,map[v][u]+=aug,v=u,u=pre[u]; } return flow; } void display() { for(int i=0;i<_V;i++) for(int j=0;j<_V;j++)cout<<i<<' '<<j<<' '<<map[i][j]<<endl; cout<<endl; } }net; int main() { #ifndef ONLINE_JUDGE freopen("data.in", "r", stdin); #endif int n,m; cin>>n>>m; net.build(n,m); // net.display(); printf("%d\n",net.sap()); return 0; }
void bfs(){ memset(d,-1,4*_V);//!!! num[d[dest]=0]++; int que[N],front,rear; front=rear=0; que[rear++]=dest; while(front!=rear){ int v=que[front++]; for(int u=0;u<_V;u++){ if(d[u]==-1&&map[u][v]){ num[d[u]=d[v]+1]++; que[rear++]=u; } } } }
5.高标预流推进(邻接表)
#include<cstdio> #include<iostream> using namespace std; // freopen("data.in","r",stdin); #include<queue> #include<cstring> #define N 1010 #define M 11000//double #define INF 100000000 int idx[N],cnt[N]; int d[N]; struct cmp{ bool operator()(const int &u,const int &v)const{ return d[u]<d[v]; } }; struct Node{ int u,v,next; int c; }; struct Graph{ Node E[M]; int first[N]; int _V,_E,src,dest; __int64 rest[N]; int in[N]; priority_queue<int,vector<int>,cmp> active; void init(int n){ _V=n,_E=0; src=0;dest=_V-1; memset(first,-1,4*_V);//!!! } void build(int house,int cust){ init(cust+2); int i,j; for(i=1;i<=house;i++) { idx[i]=-1; scanf("%d",cnt+i); } int loop,num,cap; for(i=1;i<=cust;i++) { cap=0; scanf("%d",&num); for(j=0;j<num;j++) { scanf("%d",&loop); if(idx[loop]!=-1)add(idx[loop],i,INF); else cap+=cnt[loop],idx[loop]=i; } if(cap)add(src,i,cap); scanf("%d",&num); add(i,dest,num); } } void add(int u,int v,int c){ E[_E].u=u,E[_E].v=v,E[_E].c=c,E[_E].next=first[u],first[u]=_E,_E++; E[_E].u=v,E[_E].v=u,E[_E].c=0,E[_E].next=first[v],first[v]=_E,_E++;// } void calHeight(){ memset(d,-1,sizeof(d)); d[dest]=0; int que[N],front,rear; front=rear=0; que[rear++]=dest; while(front!=rear){ int v=que[front++],u; for(int e=first[v]; e!=-1; e=E[e].next){ u=E[e].v; if(d[u]==-1){ d[u]=d[v]+1; que[rear++]=u; } } } } void preprocess(){ for(int i=0;i<_V;i++)rest[i]=in[i]=0; rest[src]=INF;active.push(src); } inline void push(int u){ for(int e=first[u]; e!=-1&&rest[u]; e=E[e].next){ int v=E[e].v,c=E[e].c; if(d[E[e].v]+1==d[u]&&E[e].c){ int aug=rest[u]<c?rest[u]:c;//!! rest[v]+=aug,rest[u]-=aug,E[e].c-=aug,E[e^1].c+=aug; if(!in[v]&&v!=dest&&v!=src){ active.push(v); in[v]=true; } } } } inline bool relable(int u){ d[u]=_V-1; for(int e=first[u]; e!=-1; e=E[e].next)if(E[e].c&&d[u]>d[E[e].v])d[u]=d[E[e].v]; d[u]++; return d[u]!=_V; } __int64 preFlowPush(){ calHeight(); preprocess(); while(!active.empty()){//!!不记录s,t int u=active.top(); push(u);//从点u进行推流 if(rest[u]&&relable(u))continue;//可以继续推流 active.pop();in[u]=false;//否则弹出队列 } return rest[dest]; } void display(){ for(int i=0; i<_V; i++){ for(int e=first[i]; e!=-1; e=E[e].next){ int u=E[e].u,v=E[e].v,c=E[e].c; cout<<u<<' '<<v<<' '<<c<<endl; } } } } net; int main() { #ifndef ONLINE_JUDGE freopen("data.in", "r", stdin); #endif int n,m; cin>>n>>m; net.build(n,m); // net.display(); printf("%d\n",net.preFlowPush()); return 0; }
6.高标预流推进(邻接阵)
#include<cstdio> #include<iostream> using namespace std; // freopen("data.in","r",stdin); #include<queue> #include<cstring> #define N 1010 #define M 11000//double #define INF 100000000 int d[N]; struct cmp{ bool operator()(const int &u,const int &v)const{ return d[u]<d[v]; } }; int idx[N]; int cnt[N]; struct Graph{ int map[N][N]; int _V,_E,src,dest; __int64 rest[N]; int in[N]; priority_queue<int,vector<int>,cmp> active; void init(int n) { _V=n; src=0;dest=_V-1; for(int i=0;i<_V;i++) for(int j=0;j<_V;j++)map[i][j]=0;//!! } void build(int house,int cust) { init(cust+2); int i,j; for(i=1;i<=house;i++) { idx[i]=-1; scanf("%d",cnt+i); } int loop,num,cap; for(i=1;i<=cust;i++) { cap=0; scanf("%d",&num); for(j=0;j<num;j++) { scanf("%d",&loop); if(idx[loop]!=-1)map[idx[loop]][i]=INF; else cap+=cnt[loop],idx[loop]=i; } if(cap) map[src][i]=cap; scanf("%d",&num); map[i][dest]=num; } } void calHeight(){ memset(d,-1,sizeof(d)); d[dest]=0; int que[N],front,rear; front=rear=0; que[rear++]=dest; while(front!=rear){ int v=que[front++]; for(int u=0;u<_V;u++){ if(d[u]==-1){ d[u]=d[v]+1; que[rear++]=u; } } } // d[src]=_V;//!! } void preprocess(){ for(int i=0;i<_V;i++)rest[i]=in[i]=0; rest[src]=INF;active.push(src); } inline void push(int u){ for(int v=0;v<_V&&rest[u];v++){ if(d[v]+1==d[u]&&map[u][v]){ int aug=rest[u]<map[u][v]?rest[u]:map[u][v];//!! rest[v]+=aug,rest[u]-=aug,map[u][v]-=aug,map[v][u]+=aug; if(!in[v]&&v!=dest&&v!=src){ active.push(v); in[v]=true; } } } } inline bool relable(int u){ d[u]=_V-1; for(int v=0;v<_V;v++)if(map[u][v]&&d[u]>d[v])d[u]=d[v]; d[u]++; return d[u]!=_V; } __int64 preFlowPush(){ calHeight(); preprocess(); while(!active.empty()){//!!不记录s,t int u=active.top(); push(u);//从点u进行推流 if(rest[u]&&relable(u))continue;//可以继续推流 active.pop();in[u]=false;//否则弹出队列 } return rest[dest]; } void display(){ for(int i=0;i<_V;i++) for(int j=0;j<_V;j++)cout<<i<<' '<<j<<' '<<map[i][j]<<endl; cout<<endl; } } net; int main() { #ifndef ONLINE_JUDGE freopen("data.in", "r", stdin); #endif int n,m; cin>>n>>m; net.build(n,m); // net.display(); printf("%d\n",net.preFlowPush()); return 0; }