[网络流24题-4]cogs729 圆桌聚餐

来源:互联网 发布:淘宝物流重量怎么填 编辑:程序博客网 时间:2024/06/07 01:09

我发现我的网络流真的建模很差。。。。这题2星的难度,我觉得我完全可以做下来,但是最终还是无法设计出一个显式的方案,或者说两个限制条件没有结合起来;最终看了hzwer神犇的题解才明白。

题目传送cogs729圆桌聚餐

首先他说有m个公司, 每个公司有pi(0im),有n张桌子,每张桌子有容量ci(0in) 求所有代表坐座位的方案

首先我就想,如果是每个单位不同的人要坐不同的桌子 那么二分图匹配要用上了。。。。然而每个桌子都有一个容量,我把它想成是一个有下界的结点,再把他拆成一条边,然而这样又难以和二分图匹配联系起来。左右思之,还是去看了下题解,发现了很巧妙的办法:

建立超级源点s和超级汇点t,从s到每个单位建立一个单位所有人为容量的边,然后从每个桌子到汇点建一条容量为桌子容量的边,再把每个单位和每个桌子连容量为1的边。。。。我只觉得这样做很妙,首先它保证了每个单位每个人桌子不同,然后他也保证了每个桌子不超人。。。。要我自己去想,我可能还没到这种高度,真的建不出来这种模。

大家有没有固定的这样建模的技巧什么的。。。。有的话一定要告诉我qwq

#include <iostream>#include <cstdio>#include <cstring>#include <cstdlib>#include <vector>#include <queue>#include <map>using namespace std;const int inf=0x3f3f3f3f;const int maxn=275;const int maxm=155;int co[maxm];int des[maxn];int m,n;struct edge{    int to,cap,rev;};vector<edge> g[maxn+maxm];void addedge(int from,int to,int cap){    g[from].push_back((edge){to,cap,g[to].size()});    g[to].push_back((edge){from,0,g[from].size()-1});}int dis[maxn+maxm+2];bool bfs(int st,int ed){    memset(dis,inf,sizeof(dis));    int head=0;    int tail=0;    int q[maxn+maxm+2];    memset(q,0,sizeof(q));    q[head]=st;    dis[st]=0;    while(head<=tail)    {        int top=q[head];        head++;        for(unsigned i=0;i<g[top].size();i++)        {            edge & e=g[top][i];            if(dis[e.to]==inf && e.cap>0)            {                dis[e.to]=dis[top]+1;                tail++;                q[tail]=e.to;            }        }    }    return dis[ed]!=inf;}int dfs(int v,int ed,int leftflow){    if(v==ed || leftflow==0)    {        return leftflow;    }    for(unsigned i=0;i<g[v].size();i++)    {        edge &e=g[v][i];        if(e.cap>0 && dis[e.to]==dis[v]+1)        {            int f;            f=dfs(e.to,ed,min(e.cap,leftflow));            if(f>0)            {                e.cap-=f;                g[e.to][e.rev].cap+=f;                return f;            }        }    }    return 0;}int dinic(int st,int ed){    int ans=0;    while(bfs(st,ed))    {        int f;        while((f=dfs(st,ed,inf))>0)        {            ans+=f;        }    }    return ans;}int main(){    freopen("roundtable.in","r",stdin);    freopen("roundtable.out","w",stdout);    bool flag=true;    int per=0;    int tabp=0;    scanf("%d%d",&m,&n);    for(int i=1;i<=m;i++)    {        scanf("%d",&co[i]);        per+=co[i];    }    for(int i=1;i<=n;i++)    {        scanf("%d",&des[i]);        tabp+=des[i];    }    if(tabp<per)    {        flag=false;    }    else    {        int s=0;        int t=m+n+1;        for(int i=1;i<=m;i++)        {            addedge(s,i,co[i]);        }        for(int i=1;i<=n;i++)        {            addedge(i+m,t,des[i]);        }        for(int i=1;i<=m;i++)        {            for(int j=1;j<=n;j++)            {                addedge(i,j+m,1);            }        }        int ans=dinic(s,t);        if(ans<per)        {            flag=false;        }        if(flag==false)        {            printf("0\n");        }        else        {            printf("1\n");            vector<int > ans[maxm+1];            for(int i=1;i<=m;i++)            {                for(unsigned j=0;j<g[i].size();j++)                {                    edge & e=g[i][j];                    if(e.cap==0)                    {                        ans[i].push_back(e.to);                    }                }            }            for(int i=1;i<=m;i++)            {                for(unsigned j=0;j<ans[i].size();j++)                {                    printf("%d ",ans[i][j]-m);                }                printf("\n");            }        }    }    return 0;}
0 0