我发现我的网络流真的建模很差。。。。这题2星的难度,我觉得我完全可以做下来,但是最终还是无法设计出一个显式的方案,或者说两个限制条件没有结合起来;最终看了hzwer神犇的题解才明白。
题目传送cogs729圆桌聚餐
首先他说有 m 个公司, 每个公司有 pi(0≤i≤m) ,有 n 张桌子,每张桌子有容量 ci(0≤i≤n) 求所有代表坐座位的方案
首先我就想,如果是每个单位不同的人要坐不同的桌子 那么二分图匹配要用上了。。。。然而每个桌子都有一个容量,我把它想成是一个有下界的结点,再把他拆成一条边,然而这样又难以和二分图匹配联系起来。左右思之,还是去看了下题解,发现了很巧妙的办法:
建立超级源点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;
}