【刷題】LOJ 6006 「網絡流 24 題」試題庫
阿新 • • 發佈:2018-08-05
urn std ret ble 多個 網絡流 屬性 template += 個正整數 \(p\) 表明該題可以屬於 \(p\) 類,接著的 \(p\) 個數是該題所屬的類型號。
題目描述
假設一個試題庫中有 \(n\) 道試題。每道試題都標明了所屬類別。同一道題可能有多個類別屬性。現要從題庫中抽取 \(m\) 道題組成試卷。並要求試卷包含指定類型的試題。試設計一個滿足要求的組卷算法。
輸入格式
第 \(1\) 行有 \(2\) 個正整數 \(k\) 和 \(n\) 。\(k\) 表示題庫中試題類型總數,\(n\) 表示題庫中試題總數。第 \(2\) 行有 \(k\) 個正整數,第 \(i\) 個正整數表示要選出的類型 \(i\) 的題數。這 \(k\) 個數相加就是要選出的總題數 \(m\) 。
接下來的 \(n\) 行給出了題庫中每個試題的類型信息。每行的第 \(1\)
輸出格式
第 \(i\) 行輸出 i:
後接類型 \(i\) 的題號。如果有多個滿足要求的方案,只要輸出一個方案。如果問題無解,則輸出 No Solution!
。
樣例
樣例輸入
3 15
3 3 4
2 1 2
1 3
1 3
1 3
1 3
3 1 2 3
2 2 3
2 1 3
1 2
1 2
2 1 2
2 1 3
2 1 2
1 1
3 1 2 3
樣例輸出
1: 1 6 8
2: 7 9 10
3: 2 3 4 5
數據範圍與提示
\(2 \leq k \leq 20, k \leq n \leq 1000\)
題解
這和圓桌聚餐問題毫無區別啊
試題和屬性分別和源點和匯點相連,屬性容量為各自的需要,試題的容量只能為 \(1\)
試題和自己的屬性相連,容量為 \(1\)
跑最大流
#include<bits/stdc++.h> #define ui unsigned int #define ll long long #define db double #define ld long double #define ull unsigned long long const int MAXN=2000+10,MAXM=MAXN*MAXN+10,inf=0x3f3f3f3f; int n,k,e=1,beg[MAXN],cur[MAXN],level[MAXN],vis[MAXN],clk,s,t,nex[MAXM<<1],to[MAXM<<1],cap[MAXM<<1],all; std::queue<int> q; template<typename T> inline void read(T &x) { T data=0,w=1; char ch=0; while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar(); if(ch=='-')w=-1,ch=getchar(); while(ch>='0'&&ch<='9')data=((T)data<<3)+((T)data<<1)+(ch^'0'),ch=getchar(); x=data*w; } template<typename T> inline void write(T x,char ch='\0') { if(x<0)putchar('-'),x=-x; if(x>9)write(x/10); putchar(x%10+'0'); if(ch!='\0')putchar(ch); } template<typename T> inline void chkmin(T &x,T y){x=(y<x?y:x);} template<typename T> inline void chkmax(T &x,T y){x=(y>x?y:x);} template<typename T> inline T min(T x,T y){return x<y?x:y;} template<typename T> inline T max(T x,T y){return x>y?x:y;} inline void insert(int x,int y,int z) { to[++e]=y; nex[e]=beg[x]; beg[x]=e; cap[e]=z; to[++e]=x; nex[e]=beg[y]; beg[y]=e; cap[e]=0; } inline bool bfs() { memset(level,0,sizeof(level)); level[s]=1; q.push(s); while(!q.empty()) { int x=q.front(); q.pop(); for(register int i=beg[x];i;i=nex[i]) if(cap[i]&&!level[to[i]])level[to[i]]=level[x]+1,q.push(to[i]); } return level[t]; } inline int dfs(int x,int maxflow) { if(x==t||!maxflow)return maxflow; vis[x]=clk; int res=0; for(register int &i=cur[x];i;i=nex[i]) if((vis[to[i]]^vis[x])&&cap[i]&&level[to[i]]==level[x]+1) { int f=dfs(to[i],min(maxflow,cap[i])); cap[i]-=f; cap[i^1]+=f; res+=f; maxflow-=f; if(!maxflow)break; } vis[x]=0; return res; } inline int Dinic() { int res=0; while(bfs())clk++,memcpy(cur,beg,sizeof(cur)),res+=dfs(s,inf); return res; } int main() { read(k);read(n); s=k+n+1,t=s+1; for(register int i=1,x;i<=k;++i)read(x),insert(s,i,x),all+=x; for(register int i=1;i<=n;++i) { insert(i+k,t,1); int m;read(m); for(register int j=1,x;j<=m;++j)read(x),insert(x,i+k,1); } if(Dinic()!=all)puts("No Solution!"); else for(register int x=1;x<=k;++x) { printf("%d:",x); for(register int i=beg[x];i;i=nex[i]) if(!cap[i]&&(i&1^1))printf(" %d",to[i]-k); puts(""); } return 0; }
【刷題】LOJ 6006 「網絡流 24 題」試題庫