題目:試題庫問題
思路:
源點S向所有試題連邊,邊權爲1。
所有試題向對應的類型連邊,權爲1。
所有類型向匯點T連邊,權爲需要的試題數量。
跑最大流並輸出路徑即可。
代碼:
#include<bits/stdc++.h>
using namespace std;
#define maxk 20
#define maxn 1000
#define maxm 100000
#define inf ((int)1e9)
#define read(x) scanf("%d",&x)
struct Edge{
int u,v,w;
Edge(){}
Edge(int uu,int vv,int ww) {u=uu,v=vv,w=ww;}
};
int K,n,m;
Edge e[maxm+5];
int h[maxm+5],nxt[maxm+5],cnt=-1;
int d[maxm+5],cur[maxn+5];
void addedge(int u,int v,int w) {
e[++cnt]=Edge(u,v,w);
nxt[cnt]=h[u];
h[u]=cnt;
}
void readin() {
memset(h,-1,sizeof(h));
memset(nxt,-1,sizeof(nxt));
read(K),read(n);
for(int i=1;i<=K;i++) {
int x;read(x);m+=x;
addedge(i,n+K+1,x);
addedge(n+K+1,i,0);
}
for(int i=1;i<=n;i++) {
int x;read(x);
addedge(0,i+K,1),addedge(i+K,0,0);
for(int j=1;j<=x;j++) {
int y;read(y);
addedge(i+K,y,1);addedge(y,i+K,0);
}
}
}
queue<int> que;
bool bfs() {
memset(d,0,sizeof(d));
d[0]=1;que.push(0);
while(!que.empty()) {
int x=que.front();que.pop();
for(int i=h[x];~i;i=nxt[i]) {
Edge y=e[i];
if(d[y.v]||!y.w) continue;
d[y.v]=d[x]+1;
que.push(y.v);
}
}
if(d[n+K+1]) return true;
return false;
}
int dfs(int x,int w) {
if(x==n+K+1) return w;
for(int& i=cur[x];~i;i=nxt[i]) {
Edge y=e[i];
if(d[y.v]-d[x]!=1||!y.w) continue;
int z=dfs(y.v,min(w,y.w));
if(z) {
e[i].w-=z;
e[i^1].w+=z;
return z;
}
}
return 0;
}
int dinic() {
int ans=0;
while(bfs()) {
for(int i=0;i<=n+K+1;i++) cur[i]=h[i];
while(int x=dfs(0,inf)) ans+=x;
}
return ans;
}
vector<int> a[maxn+5];
void print() {
for(int i=0;i<=cnt;i++) if(e[i].w&&e[i].u>0&&e[i].u<=K&&e[i].v>K&&e[i].v<n+K+1) a[e[i].u].push_back(e[i].v-K);
for(int i=1;i<=K;i++) {
printf("%d:",i);
for(int j=0;j<a[i].size();j++) printf(" %d",a[i][j]);
printf("\n");
}
}
int main() {
readin();
int ans=dinic();
if(ans!=m) printf("No Solution!");
else print();
return 0;
}