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

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

题目传送cogs729圆桌聚餐

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

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

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

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

#include 
#include 
#include 
#include 
#include 
#include 
#include 

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 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;iif(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;iif(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(tabpfalse;
    }
    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(ansfalse;
        }
        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;jif(e.cap==0)
                    {
                        ans[i].push_back(e.to);
                    }
                }
            }
            for(int i=1;i<=m;i++)
            {
                for(unsigned j=0;jprintf("%d ",ans[i][j]-m);
                }
                printf("\n");
            }
        }
    }
    return 0;
}

你可能感兴趣的:(算法,noip,网络流专区,cogs,网络流24题)