[網絡流24題07] 試題庫問題

題面傳送機

Sol

網絡流 網絡流 可怕的網絡流
建圖方式
1,建立超源(S)匯(E)點
2,每一個題型向E連有向邊 流量爲所需題目個數
3,每道題向所屬題型連有向邊 流量爲1
4,S向題連有向邊 流量爲1
判斷是否成卷就看最大流是否大於等於總需題目量了
求答案的方法(從代碼裏搬過來的)

/*************************
兩種求答案的方法 , 一個是記錄每一條邊
的兩點 , 再枚舉所有邊如果這條邊是由類
型射向題目的 , 且邊權 > 0那麼就是符合的
另外一個是枚舉每一個類型找邊權大於0的邊
剩下的代碼表示
**************************/

Code

#include <iostream>
#include <cstdio>
#include <cctype>
#include <cstring>
#define inc(i) (i = -(~i))
#define dec(i) (i = ~(-i))
using namespace std;

namespace fast
{
    inline char Getchar()
    {
        static char buf[100001] , *p1 = buf , *p2 = buf;
        return p1 == p2 && (p2 = (p1 = buf) + fread(buf , 1 , 100000 , stdin) , p1 == p2) ? EOF : *p1 ++;
    }
    inline int read()
    {
        int num = 0; char c = 0;
        while(!isdigit(c)) c = Getchar();
        while(isdigit(c)) num = num * 10 + c - '0' , c = Getchar();
        return num;
    }
}
using namespace fast;

const int N = 1000 + 7 , M = 50000 + 7 , INF = 1e9 + 7;
int S , E , Dep[N * 2] , Sum;
int k , n , Head[N * 2] , Node[M] , W[M] , Next[M] , tot = 1;
struct Queue
{
    int l , r , Que[M];
    inline void cls() {l = 100 , r = 99;}
    inline bool full() {return r >= l;}
    inline int top() {return Que[l];}
    inline void pop() {inc(l);}
    inline void push(int x) {Que[inc(r)] = x;}
}Q;

inline void Add(int u , int v , int w)
{
    Next[inc(tot)] = Head[u] , Head[u] = tot , Node[tot] = v , W[tot] = w;
    Next[inc(tot)] = Head[v] , Head[v] = tot , Node[tot] = u , W[tot] = 0;
}

inline bool BFS()
{
    memset(Dep , 0 , sizeof(Dep)) , Q.cls();
    int u , v;
    Dep[S] = 1 , Q.push(S);
    while(Q.full())
    {
        u = Q.top(); Q.pop();
        for(int i = Head[u] ; i ; i = Next[i])
        {
            v = Node[i];
            if(!Dep[v] && W[i])
            {
                Dep[v] = Dep[u] + 1;
                Q.push(v);
            }
        }
    }
    return Dep[E];
}

inline int DFS(int u , int lastc)
{
    if(u == E || !lastc)    return lastc;
    int v , Flow , Now = 0;
    for(int i = Head[u] ; i ; i = Next[i])
    {
        v = Node[i];
        if(Dep[u] == Dep[v] - 1 && W[i])
        {
            Flow = DFS(v , min(lastc , W[i]));
            if(Flow)
            {
                Now += Flow;
                W[i] -= Flow;
                W[i ^ 1] += Flow;
                if(Now == lastc)    break;
            }
        }
    }
    return Now;
}

inline bool Max_Flow()
{
    int Ans = 0;
    while(BFS())
        Ans += DFS(S , INF);
    return Ans >= Sum;
}

int main()
{
    k = read() , n = read();
    S = k + n + 1 , E = S + 1;
    for(int i = 1 , w ; i <= k ; inc(i))
        w = read() , Add(i , E , w) , Sum += w;
    for(int i = 1 , p , q ; i <= n ; inc(i))
    {
        p = read() + 1;
        while(dec(p))
            q = read() , Add(i + k , q , 1);
        Add(S , i + k , 1);
    }
    if(Max_Flow())
    {
        /***********************************
        兩種求答案的方法 , 一個是記錄每一條邊
        的兩點 , 再枚舉所有邊如果這條邊是由類
        型射向題目的 , 且邊權 > 0那麼就是符合的
        另外一個是枚舉每一個類型找邊權大於0的邊
        剩下的代碼表示
        ************************************/
        for(int u = 1 , v ; u <= k ; inc(u))
        {
            printf("%d:" , u);
            for(int i = Head[u] ; i ; i = Next[i])
            {
                v = Node[i];
                if(v <= k + n && W[i])    
                    printf(" %d" , v - k);
            }
            puts("");
        }
    }
    else
        puts("No Solution!");
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章