和圆桌问题非常类似,最大流跑出来然后用返回的增广路的流量输出虐之
#include<cstdio>
#include<cstring>
#include<queue>
#include<algorithm>
const int MAXN=1000+5;
const int INF=1e9+7;
struct Edge
{
int nxt;
int to;
int f;
}edge[MAXN<<5];
int num=1;
int head[MAXN];
void add(int from,int to,int f)
{
edge[++num].nxt=head[from];
edge[num].to=to;
edge[num].f=f;
head[from]=num;
edge[++num].nxt=head[to];
edge[num].f=0;
edge[num].to=from;
head[to]=num;
}
int src;
int sink;
int dist[MAXN];
bool vis[MAXN];
bool BFS()
{
std::memset(dist,0,sizeof(dist));
std::memset(vis,0,sizeof(vis));
std::queue<int>q;
q.push(src);
vis[src]=1;
dist[src]=0;
while(!q.empty())
{
int u=q.front();
q.pop();
for(int i=head[u];i;i=edge[i].nxt)
{
int v=edge[i].to;
if(!vis[v]&&edge[i].f)
{
dist[v]=dist[u]+1;
vis[v]=1;
q.push(v);
}
}
}
return vis[sink];
}
int dfs(int x,int delta)
{
if(x==sink)
{
return delta;
}
int res=0;
for(int i=head[x];i;i=edge[i].nxt)
{
int v=edge[i].to;
if(edge[i].f&&dist[v]==dist[x]+1)
{
int dd=dfs(v,std::min(delta,edge[i].f));
edge[i].f-=dd;
edge[i^1].f+=dd;
delta-=dd;
res+=dd;
}
}
return res;
}
int dinic()
{
int ans=0;
while(BFS())
{
ans+=dfs(src,INF);
}
return ans;
}
int num1[MAXN];
int k;
int n;
void print()
{
for(int p=n+1,l=1;p<=n+k;p++,l++)
{
printf("%d:",l);
for(int i=head[p];i;i=edge[i].nxt)
{
int v=edge[i].to;
if(v==sink) continue;
if(edge[i].f)
{
printf("%d ",v);
}
}
printf("\n");
}
}
int main()
{
std::scanf("%d%d",&k,&n);
int m=0;
for(int i=1;i<=k;i++)
{
std::scanf("%d",num1+i);
m+=num1[i];
}
src=0;
sink=n+k+1;
for(int i=1;i<=n;i++)
{
add(src,i,1);
}
for(int i=1;i<=n;i++)
{
int p;
std::scanf("%d",&p);
for(int j=1;j<=p;j++)
{
int kk;
std::scanf("%d",&kk);
add(i,kk+n,1);
}
}
for(int i=1;i<=k;i++)
{
int p=i+n;
add(p,sink,num1[i]);
}
int ans=dinic();
if(ans==m)
{
print();
}
else
{
std::printf("No Solution!\n");
}
return 0;
}