POJ-1087 A Plug for UNIX 网络流

根据关系建一个图,然后就是后面的插座的传递闭包,一个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;

}

你可能感兴趣的:(unix)