zoukankan      html  css  js  c++  java
  • 【洛谷 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('
    ');
        }
        else printf("No Solution!
    ");
        return 0;
    }
    
    
  • 相关阅读:
    javascript获取id元素
    小米供应链
    几个极限的证明
    第一章 实数
    当a在什么范围取值时,方程|x方-5x|=a有且只有两个相异实根
    壮壮的西城学探究里面的x=1,x=-1
    三角形的边长注意问题
    x方+x+1, x方-x+1无实根,不可能为0
    一个混合电路
    串联电路的电流处处相等
  • 原文地址:https://www.cnblogs.com/Qihoo360/p/10197894.html
Copyright © 2011-2022 走看看