试题库问题(网络流24题)
题意
有n道题,每个题有一些类别属性,先现出k个属性各需要的题数,一道题只能在一种类别。
输出方案,没有则输出"No Solution!"
(2 <=k<= 20, k<=n<= 1000)
题解
还是比较基础,把试题和属性分成两部分,试题与属性之间连边流量为1,源点与试题之间连边流量为1,属性与汇点连边流量为需要的题数。
最后看最大流是否为总共需要的题数,输出方案则枚举看是否满流。
#include<bits/stdc++.h> using namespace std; const int maxn=1006; const int maxm=1000006; int n,m,k; int cnt=1,s,t,head[maxn]; struct edge{ int x,y,val,next; }e[maxm]; template<class T>inline void read(T &x){ x=0;char ch=getchar(); while(!isdigit(ch)) ch=getchar(); while(isdigit(ch)) {x=(x<<1)+(x<<3)+(ch^48);ch=getchar();} } void add(int x,int y,int val){ e[++cnt]=(edge){x,y,val,head[x]}; head[x]=cnt; } int d[maxn]; bool bfs(){ queue<int> q; memset(d,0,sizeof(d)); q.push(s);d[s]=1; while(!q.empty()){ int x=q.front(); q.pop(); for(int i=head[x];i;i=e[i].next){ int y=e[i].y; if(e[i].val&&!d[y]){ d[y]=d[x]+1; if(y==t) return true; q.push(y); } } } return false; } int dfs(int x,int flow){ if(x==t) return flow; int rest=flow,k; for(int i=head[x];i;i=e[i].next){ int y=e[i].y; if(d[y]==d[x]+1&&e[i].val){ k=dfs(y,min(rest,e[i].val)); if(!k) d[y]=0; e[i].val-=k; e[i^1].val+=k; rest-=k; } } return flow-rest; } int dinic(){ int res=0; while(bfs()) res+=dfs(s,0x3f3f3f); return res; } int main(){ scanf("%d%d",&k,&n); s=0;t=k+n+1; for(int i=1;i<=k;i++){ int x;read(x); add(i+n,t,x); add(t,i+n,0); m+=x; } for(int i=1;i<=n;i++){ add(s,i,1); add(i,s,0); int tot;read(tot); for(int j=1;j<=tot;j++){ int x;read(x); add(i,x+n,1); add(x+n,i,0); } } int ans=dinic(); if(ans!=m) {printf("No Solution!");return 0;} for(int i=n+1;i<=n+k;i++){ printf("%d: ",i-n); for(int j=head[i];j;j=e[j].next) if(e[j].val) printf("%d ",e[j].y); putchar(10); } }