[Loj]#6004. 「网络流 24 题」圆桌聚餐

来源:互联网 发布:淘宝二手笔记本怎么样 编辑:程序博客网 时间:2024/06/07 03:32

建立源点s与所有单位连边,建立汇点T将所有餐桌与t相连,再将单位与餐桌各连上容量为1的边。

跑一遍最大流即可。

输出路径时,只要查看改变是否有流即可

#include <cstdio>#include <queue>#include <algorithm>#include <cstring>using namespace std;const int N=1005,INF=1<<29;int m,n,x,sum;struct node {int nxt,ro,to,flow;}e[78000];int dis[N];int cur[N];bool vis[N];int head[N],tot=2;inline void add(int u,int v,int ro){e[tot].to=v,e[tot].ro=ro,e[tot].nxt=head[u],head[u]=tot,tot++;e[tot].to=u,e[tot].ro=0,e[tot].nxt=head[v],head[v]=tot,tot++;}inline bool bfs(int s,int t){register int i;memset(vis,0,sizeof(vis));queue<int> q;dis[s]=0;vis[s]=1;q.push(s);while (!q.empty()){int x=q.front();q.pop();for (i=head[x];i;i=e[i].nxt){if (!vis[e[i].to]&&e[i].ro>e[i].flow){q.push(e[i].to);vis[e[i].to]=1;dis[e[i].to]=dis[x]+1;}}}return vis[t];}int s,t;inline int dfs(int x,int a){if (x==t||a==0) return a;int flow=0,f;for (int& i=cur[x];i;i=e[i].nxt){if (dis[x]+1==dis[e[i].to]&&((f=dfs(e[i].to,min(a,e[i].ro-e[i].flow)))>0)){e[i].flow+=f;e[i^1].flow-=f;flow+=f;a-=f;if (a==0) break;}}return flow;}inline int dinic(int s,int t){int flow=0;while (bfs(s,t)){for (int i=0;i<=n+m+1;i++) cur[i]=head[i];flow+=dfs(s,INF);}return flow;}int main(){register int i,j;scanf("%d %d",&m,&n);s=0;t=n+m+1;//memset(head,-1,sizeof(head));for (i=1;i<=m;i++) scanf("%d",&x),add(s,i,x),sum+=x;for (i=1;i<=n;i++){scanf("%d",&x);for (j=1;j<=m;j++) add(j,i+m,1);add(i+m,t,x);}int mf=dinic(s,t);if (mf<sum) printf("0");else {puts("1");for (i=1;i<=m;i++){for (j=head[i];j;j=e[j].nxt){if (e[j].flow==1) printf("%d ",e[j].to-m);}printf("\n");}}}


原创粉丝点击