传送门
呜呜,好感动,这这真是网络流的清流啊
被感动哭了
− − − − − − − − − − − − − − − − − − − − − − − − − − − − \color{Red}---------------------------- −−−−−−−−−−−−−−−−−−−−−−−−−−−−
分析一下题目,就大概知道只一个类似二分图匹配的问题
我 们 把 m 个 单 位 放 在 左 边 , n 个 桌 子 放 在 右 边 我们把m个单位放在左边,n个桌子放在右边 我们把m个单位放在左边,n个桌子放在右边
由于每个单位的人只能在任意一张桌子上做一个人
结 论 : 每 个 单 位 向 每 个 桌 子 连 一 条 流 量 为 1 的 边 \color{Red}结论:每个单位向每个桌子连一条流量为1的边 结论:每个单位向每个桌子连一条流量为1的边
每个单位只有 r [ i ] r[i] r[i]个人
结 论 : 源 点 向 每 个 单 位 连 一 条 流 量 r [ i ] 的 边 \color{Red}结论:源点向每个单位连一条流量r[i]的边 结论:源点向每个单位连一条流量r[i]的边
每个桌子只容纳 c [ i ] 个 人 c[i]个人 c[i]个人
结 论 : 每 个 桌 子 向 源 点 连 一 条 流 量 c [ i ] 的 边 \color{Red}结论:每个桌子向源点连一条流量c[i]的边 结论:每个桌子向源点连一条流量c[i]的边
连 的 这 些 边 都 是 起 到 一 个 限 制 作 用 , 只 要 从 s 到 t 的 路 线 流 量 在 范 围 内 就 合 法 连的这些边都是起到一个限制作用,只要从s到t的路线流量在范围内就合法 连的这些边都是起到一个限制作用,只要从s到t的路线流量在范围内就合法
至于方案,枚举每个单位的所有边,如果流量为0说明选了对应的桌子
#include <bits/stdc++.h>
using namespace std;
const int maxn=2e5+10;
const int inf=1e9;
int n,m,s,t,r[maxn],c[maxn],dis[maxn],sumn;
struct edge{
int to,flow,nxt;
}d[maxn]; int head[maxn],cnt=1;
void add(int u,int v,int flow){
d[++cnt]=(edge){v,flow,head[u]},head[u]=cnt;
}
bool bfs()
{
queue<int>q;
for(int i=0;i<=t;i++) dis[i]=0;
dis[s]=1;
q.push( s );
while( !q.empty() )
{
int u=q.front(); q.pop();
for(int i=head[u];i;i=d[i].nxt )
{
int v=d[i].to;
if( dis[v]==0&&d[i].flow )
{
dis[v]=dis[u]+1;
if( v==t ) return true;
q.push( v );
}
}
}
return false;
}
int dinic(int u,int flow)
{
if( u==t ) return flow;
int res=flow;
for(int i=head[u];i&&res;i=d[i].nxt)
{
int v=d[i].to;
if( dis[v]==dis[u]+1&&d[i].flow )
{
int temp=dinic(v,min(res,d[i].flow) );
if( temp==0 ) dis[v]=0;
res-=temp;
d[i].flow-=temp;
d[i^1].flow+=temp;
}
}
return flow-res;
}
int main()
{
cin >> m >> n;
s=0,t=n+m+1;
for(int i=1;i<=m;i++)
{
cin >> r[i];
sumn+=r[i];
add( s,i,r[i] ); add( i,s,0 );
}
for(int i=1;i<=n;i++)
{
cin >> c[i];
add(i+m,t,c[i] ); add(t,i+m,0 );
}
for(int i=1;i<=m;i++)
for(int j=1;j<=n;j++)
add(i,j+m,1),add(j+m,i,0);
int ans=0;
while( bfs() ) ans+=dinic(s,inf);
if( ans!=sumn ) cout << 0;
else
{
cout << 1 << '\n';
for(int i=1;i<=m;i++)
{
for(int j=head[i];j;j=d[j].nxt)
{
int v=d[j].to;
if( !d[j].flow&&v!=s ) cout << v-m << " ";
}
cout << '\n';
}
}
}