【洛谷 P2763】 試題庫問題(最大流)
阿新 • • 發佈:2018-12-29
6/23
這是網路流23題裡我第一個沒看題解自己寫出來一遍過的。。
這題應該是最簡單的模型了吧。
從源點向每個型別連一條流量為這個型別要的題數,再從每個型別向可以屬於這個型別的所有試題連一條流量為1的邊,最後從所有試題向匯點連一條流量為1的邊。
跑最大流就行。判斷邊有沒有流量。
// luogu-judger-enable-o2 #include <cstdio> #include <queue> #define INF 2147483647 using namespace std; const int MAXN = 100010; inline int read(){ int s = 0, w = 1; char ch = getchar(); while(ch < '0' || ch > '9'){ if(ch == '-') w = -1; ch = getchar(); } while(ch >= '0' && ch <= '9'){ s = s * 10 + ch - '0'; ch = getchar(); } return s * w; } struct Edge{ int next, to, from, rest; }e[MAXN]; int s, t, num = 1, n, m, a; int head[MAXN]; inline void Add(int from, int to, int flow){ e[++num] = (Edge){ head[from], to, from, flow }; head[from] = num; e[++num] = (Edge){ head[to], from, to, 0 }; head[to] = num; } int flow[MAXN], pre[MAXN], dfn[MAXN], Time, now, sum; queue <int> q; int re(){ pre[t] = 0; flow[s] = INF; q.push(s); dfn[s] = ++Time; while(q.size()){ now = q.front(); q.pop(); for(int i = head[now]; i; i = e[i].next) if(dfn[e[i].to] != Time && e[i].rest){ dfn[e[i].to] = Time; q.push(e[i].to); flow[e[i].to] = min(flow[now], e[i].rest); pre[e[i].to] = i; } } return pre[t]; } int dinic(){ int ans = 0; while(re()){ ans += flow[t]; now = t; while(now != s){ e[pre[now]].rest -= flow[t]; e[pre[now] ^ 1].rest += flow[t]; now = e[pre[now]].from; } } return ans; } int main(){ s = 99999; t = 100000; n = read(); m = read(); for(int i = 1; i <= n; ++i){ sum += a = read(); Add(s, i, a); } for(int i = 1; i <= m; ++i){ a = read(); for(int j = 1; j <= a; ++j) Add(read(), i + 1010, 1); Add(i + 1010, t, 1); } if(dinic() == sum) for(int i = 1; i <= n; ++i){ printf("%d: ", i); for(int j = head[i]; j; j = e[j].next) if(e[j].to != s && !e[j].rest) printf("%d ", e[j].to - 1010); putchar('\n'); } else printf("No Solution!\n"); return 0; }