比较模板的网络流匹配了
明 显 是 拿 试 卷 去 匹 配 类 型 明显是拿试卷去匹配类型 明显是拿试卷去匹配类型
由 于 一 张 试 卷 只 能 贡 献 给 一 种 类 型 , 所 以 s 向 试 卷 连 流 量 1 的 边 来 限 制 一 下 由于一张试卷只能贡献给一种类型,所以s向试卷连流量1的边来限制一下 由于一张试卷只能贡献给一种类型,所以s向试卷连流量1的边来限制一下
每 张 试 卷 可 以 流 入 一 些 类 型 , 向 对 应 的 类 型 建 边 , 流 量 1 每张试卷可以流入一些类型,向对应的类型建边,流量1 每张试卷可以流入一些类型,向对应的类型建边,流量1
每 种 类 型 需 要 被 匹 配 x 次 , 所 以 类 型 向 t 连 边 , 流 量 为 x 每种类型需要被匹配x次,所以类型向t连边,流量为x 每种类型需要被匹配x次,所以类型向t连边,流量为x
输出方案也好办
遍历每种类型的边,如果边的流量是0(那么反向边是1)说明选过了,可以输出
#include <bits/stdc++.h>
using namespace std;
const int inf=1e9;
const int maxn=2e5+10;
int n,m,k,s,t;
struct edge{
int to,nxt,flow;
}d[maxn]; int head[maxn],cnt=1;
void add(int u,int v,int flow){
d[++cnt]=(edge){v,head[u],flow},head[u]=cnt;
}
int dis[maxn],shu[maxn];
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;
}
if( res==0 ) break;
}
return flow-res;
}
int main()
{
cin >> k >> n;
s=0,t=k+n+1;
int sumn=0;
for(int i=1;i<=k;i++)
{
cin >> shu[i];
add( i+n,t,shu[i] );
add( t,i+n,0 );
sumn+=shu[i];
}
for(int i=1;i<=n;i++)
{
add(s,i,1); add(i,s,0);
int f,x; cin >> f;
while( f-- )
{
cin >> x;
add(i,x+n,1);
add(x+n,i,0);
}
}
while( bfs() )
sumn-=dinic(s,inf);
if( sumn!=0 ) cout << "No Solution!";
else
{
for(int i=n+1;i<=k+n;i++)
{
cout << i-n << ": ";
for(int j=head[i];j;j=d[j].nxt )
{
int v=d[j].to;
if( v==t ) continue;
if( d[j].flow ) cout << d[j].to << " ";
}
cout << '\n';
}
}
}