现在的位置: 首页 > 综合 > 正文

POJ-1087 A Plug for UNIX 网络流

2013年01月06日 ⁄ 综合 ⁄ 共 2015字 ⁄ 字号 评论关闭

根据关系建一个图,然后就是后面的插座的传递闭包,一个floyd构边。

代码如下:

#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <map>
#include <string>
#define INF 0x3fffffff
#define CN(x) (255+(x))
#define MN(x) (555+(x))
#define MAXN 500
using namespace std;

int N, M, K, rec[MAXN], idx, cnt;
int head[1000], dis[1000], que[1000], front, tail;
const int SS = 0, TT = 998;
bool R[505][505];

map<string,int>mp;

struct Edge {
    int v, cap, next;
}e[500000];

void addedge(int a, int b, int cap) {
    ++idx;
    e[idx].v = b, e[idx].cap = cap;
    e[idx].next = head[a], head[a] = idx;
    ++idx;
    e[idx].v = a, e[idx].cap = 0;
    e[idx].next = head[b], head[b] = idx;
}

bool bfs() {
    int pos;
    memset(dis, 0xff, sizeof (dis));
    dis[SS] = front = tail = 0;
    que[++tail] = SS;
    while (front != tail) {
        pos = que[++front];
        for (int i = head[pos]; i != -1; i = e[i].next) {
            if (e[i].cap > 0 && dis[e[i].v] == -1) {
                dis[e[i].v] = dis[pos] + 1;    
                if (e[i].v == TT) return true;
                que[++tail] = e[i].v;
            }
        }
    }
    return false;
}

int dfs(int u, int flow) {
    if (u == TT) {
        return flow;    
    }
    int f, tf = 0;
    for (int i = head[u]; i != -1; i = e[i].next) {
        if (dis[u]+1 == dis[e[i].v] && e[i].cap > 0 && (f = dfs(e[i].v, min(e[i].cap, flow-tf)))) {
            e[i].cap -= f, e[i^1].cap += f;
            tf += f;
            if (tf == flow) return flow;
        }
    }
    if (!tf) dis[u] = -1;
    return tf;
}

int dinic() {
    int ret = 0;
    while (bfs()) {
        ret += dfs(SS, INF);    
    }    
    return ret;
}

void floyd() {
    for (int k = 1; k <= cnt; ++k) {
        for (int i = 1; i <= cnt; ++i) {
            for (int j = 1; j <= cnt; ++j) {
                R[i][j] |= R[i][k] & R[k][j];    
            }    
        }
    }    
}

int main() {
    char name[30], str[30];
    while (scanf("%d", &N) == 1) {
        cnt = 0;
        idx = -1;
        memset(rec, 0, sizeof (rec));
        memset(head, 0xff, sizeof (head));
        memset(R, 0, sizeof (R));
        mp.clear();
        for (int i = 1; i <= N; ++i) {
            scanf("%s", name);
            if (!mp.count(name)) {
                mp[name] = ++cnt;
            }
            ++rec[mp[name]]; // 将插座的信息统计好
        }
        scanf("%d", &M);
        for (int i = 1; i <= M; ++i) {
            scanf("%s %s", str, name);
            if (!mp.count(name)) {
                mp[name] = ++cnt;
            }
            addedge(SS, i, 1);
            addedge(i, CN(mp[name]), 1);
        }
        for (int i = 1; i <= cnt; ++i) {
            addedge(CN(i), MN(i), rec[i]);
            addedge(MN(i), TT, INF);
        }
        scanf("%d", &K);
        for (int i = 1; i <= K; ++i) {
            scanf("%s %s", str, name);
            if (!mp.count(str)) mp[str] = ++cnt;
            if (!mp.count(name)) mp[name] = ++cnt;
            R[mp[str]][mp[name]] = true;
        }
        floyd();
        for (int i = 1; i <= cnt; ++i) {
            for (int j = 1; j <= cnt; ++j) {
                if (R[i][j]) {
                    addedge(CN(i), CN(j), INF);
                }
            }
        }
        printf("%d\n", M-dinic());
    }
    return 0;
}

抱歉!评论已关闭.