1. 程式人生 > >【洛谷 P2763】 試題庫問題(最大流)

【洛谷 P2763】 試題庫問題(最大流)

題目連結

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;
}