当前位置:编程学习 > C/C++ >>

HDU 4292 Food(拆点,最大流)

[cpp] 
/*
最大流问题
拆点:增加超级源点和汇点,源点于食物相连,边的权值为食物最大量;饮料与汇点相连,变得权值为饮料的最大量;
将人拆分成两个,一个与食物相连,一个与饮料相连,权值可以为1也可以为INF,无影响。
将拆分后的两个节点相连,边的权值为1
*/ 
 
#include <cstdio> 
#include <cstring> 
const int nMax = 2007; 
const int INF = 0x3fffffff; 
int N, F, D; 
int NN; 
struct Adj 

    int v, w; 
    int next; 
    Adj(){} 
    Adj(int v, int w, int next):v(v), w(w), next(next){} 
}adj[100 * nMax]; 
int head[nMax]; 
int cnt; 
int dis[nMax], num[nMax]; 
 
void addEdge(int u, int v, int w) 

    adj[cnt] = Adj(v, w, head[u]); 
    head[u] = cnt ++; 
    adj[cnt] = Adj(u, 0, head[v]); 
    head[v] = cnt ++; 

 
int min(int a, int b) 

    return a < b ? a : b; 

 
int dfs(int u, int s, int d, int cost) 

    if(u == d) return cost; 
    int i; 
    int ans = 0; 
    int _min = NN; 
    for(i = head[u]; i != -1; i = adj[i].next) 
    { 
        int v = adj[i].v; 
        if(adj[i].w) 
        { 
            if(dis[v] + 1 == dis[u]) 
            { 
                int t = dfs(v, s, d, min(adj[i].w, cost)); 
                adj[i].w -= t; 
                adj[i ^ 1].w += t; 
                ans += t; 
                cost -= t; 
                if(dis[s] == NN) return ans; 
                if(!cost) break; 
            } 
            if(_min > dis[v]) 
                _min = dis[v]; 
        } 
    } 
    if(!ans) 
    { 
        if(-- num[dis[u]] == 0) dis[s] = NN; 
        dis[u] = _min + 1; 
        ++ num[dis[u]]; 
    } 
    return ans; 

 
int isap(int s, int d) 

    memset(dis, 0, sizeof(dis)); 
    memset(num, 0, sizeof(num)); 
    num[0] = NN; 
    int ans = 0; 
    while(dis[s] < NN) 
        ans += dfs(s, s, d, INF); 
    return ans; 

 
int main() 

    //freopen("e://data.in", "r", stdin); 
    while(scanf("%d%d%d", &N, &F, &D) != EOF) 
    { 
        int i, j; 
        int a; 
        char s[nMax]; 
        memset(head, -1, sizeof(head)); 
        cnt = 0; 
        for(i = 1; i <= F; ++ i)  
        { 
            scanf("%d", &a); 
            addEdge(0, i, a); 
        } 
        for(i = 1; i <= D; ++ i) 
        { 
            scanf("%d", &a); 
            addEdge(F + 2 * N + i, F + 2 * N + D + 1, a); 
        } 
        for(i = 1; i <= N; ++ i) 
        { 
            addEdge(F + i, F + N + i, 1); 
        } 
        for(i = 1; i <= N; ++ i) 
        { 
            scanf("%s", s + 1); 
            for(j = 1; j <= F; ++ j) 
                if(s[j] == 'Y') 
                    addEdge(j, F + i, INF); 
        } 
        for(i = 1; i <= N; ++ i) 
        { 
            scanf("%s", s + 1); 
            for(j = 1; j <= D; ++ j) 
                if(s[j] == 'Y') 
                    addEdge(F + N + i, F + 2 * N + j, INF); 
        } 
        NN = F + 2 * N + D + 2; 
        int ans = isap(0, NN - 1); 
        printf("%d\n", ans); 
    } 
    return 0; 

补充:软件开发 , C++ ,
CopyRight © 2022 站长资源库 编程知识问答 zzzyk.com All Rights Reserved
部分文章来自网络,