[网络流24题] 圆桌问题 (最大流)

洛谷传送门 LOJ传送门

这估计是$24$题里建图最好想的了吧..

源点$S$向每个单位连流量为$r_{i}$的边,每个圆桌向汇点$T$连流量为$c_{i}$的边,每个单位和每个圆桌之间都连一条流量为$1$的边

然后上$Dinic$就行了

最终的方案里,如果一个单位流向一个圆桌的流量为$0$,说明这条边被用上了,即这个单位里有一个人被分配到了这个圆桌

把Dinic模板打错了调了30min

  1 #include <vector>
  2 #include <cstdio>
  3 #include <cstring>
  4 #include <algorithm>
  5 #define N1 505
  6 #define M1 50010
  7 #define ll long long
  8 #define dd double
  9 #define inf 0x3f3f3f3f
 10 using namespace std;
 11 
 12 int gint()
 13 {
 14     int ret=0,fh=1;char c=getchar();
 15     while(c<'0'||c>'9'){if(c=='-')fh=-1;c=getchar();}
 16     while(c>='0'&&c<='9'){ret=ret*10+c-'0';c=getchar();}
 17     return ret*fh;
 18 }
 19 
 20 int n,m,S,T;
 21 struct Edge{
 22 int head[N1],to[M1<<1],nxt[M1<<1],flow[M1<<1],cte;
 23 void ae(int u,int v,int F)
 24 {
 25     cte++; to[cte]=v; flow[cte]=F;  
 26     nxt[cte]=head[u]; head[u]=cte;
 27 }
 28 }e;
 29 
 30 int que[N1],hd,tl,cur[N1],dep[N1];
 31 vector<int>pro[N1];
 32 
 33 int bfs()
 34 {
 35     int x,j,v;
 36     memset(dep,-1,sizeof(dep)); memcpy(cur,e.head,sizeof(cur));
 37     hd=1,tl=0; que[++tl]=S; dep[S]=0;
 38     while(hd<=tl)
 39     {
 40         x=que[hd++];
 41         for(j=e.head[x];j;j=e.nxt[j])
 42         {
 43             v=e.to[j]; if(e.flow[j]<=0||dep[v]!=-1) continue;
 44             dep[v]=dep[x]+1; que[++tl]=v;
 45         }
 46     }
 47     return dep[T]!=-1;
 48 }
 49 
 50 int dfs(int x,int limit)
 51 {
 52     int j,v,flow,ans=0;
 53     if(!limit||x==T) return limit;
 54     for(j=cur[x];j;j=e.nxt[j])
 55     {
 56         cur[x]=j; v=e.to[j]; 
 57         if( dep[v]==dep[x]+1 && (flow=dfs(v,min(limit,e.flow[j])))  ) 
 58         {
 59             limit-=flow; ans+=flow;
 60             e.flow[j]-=flow; e.flow[j^1]+=flow;
 61             if(!limit) break;
 62         }
 63     }
 64     return ans;
 65 }
 66 
 67 int Dinic()
 68 {
 69     int ans=0,flow;
 70     bfs(); flow=dfs(S,inf);
 71     while(bfs())
 72     {
 73         flow=dfs(S,inf);
 74         if(!flow) break;
 75         ans+=flow;
 76     }
 77     return ans;
 78 }
 79 
 80 int a[N1],b[N1];
 81 
 82 int main()
 83 {
 84     scanf("%d%d",&m,&n);
 85     int i,j,v,ans; e.cte=1; S=m+n+1,T=m+n+2;
 86     for(i=1;i<=m;i++) scanf("%d",&a[i]), e.ae(S,i,a[i]), e.ae(i,S,0);
 87     for(i=1;i<=n;i++) scanf("%d",&b[i]), e.ae(m+i,T,b[i]), e.ae(T,m+i,0);
 88     for(i=1;i<=m;i++) for(j=m+1;j<=m+n;j++) e.ae(i,j,1), e.ae(j,i,0);
 89     ans=Dinic();
 90     for(i=1;i<=m;i++)
 91     {
 92         for(j=e.head[i],ans=0;j;j=e.nxt[j]){ v=e.to[j]; if(!e.flow[j]) ans++; }
 93         if(ans<a[i]){ puts("0"); return 0; }
 94     }
 95     for(i=1,puts("1");i<=m;puts(""),i++) 
 96     {
 97         for(j=e.head[i];j;j=e.nxt[j])
 98         {
 99             v=e.to[j]; 
100             if(!e.flow[j]) printf("%d ",v-m);
101         }
102     }
103     return 0;
104 }
原文地址:https://www.cnblogs.com/guapisolo/p/10283025.html