UVA 753 A Plug for UNIX

来源:互联网 发布:泰安房产每日成交数据 编辑:程序博客网 时间:2024/05/20 21:23

A Plug for UNIX

题目大意:有n个插座,m个设备和k种转换器,转换器可以有无数多个,要求插的设备尽量多,问最少剩几个不匹配的设备
解题思路:网络流问题,用0表示源点s,n+m+1表示汇点t,1~n表示设备,n+1~n+m表示插座
将源点s与每个插座相连,容量为1,设备与t相连,容量为1,设备与插座相连,容量INF
求出s-t最大流用总设备数减去就得到最后答案

#include <cstdio>#include <iostream>#include <algorithm>#include <vector>#include <queue>#include <string>#include <string.h>#include <cmath>using namespace std;#define INF 0x3f3f3f3fstruct Edge {    int from, to, cap, flow;    Edge(int fr, int t, int c, int f):from(fr),to(t),cap(c),flow(f) {}};vector<Edge> edges; //是边数俩倍因为有反弧vector<int> G[1000]; //G[i][j]表示结点i的第j条边在edges中的序号int m, n, s, t, cou;int a[1000],b[1000];string c[1000];int cg[1000][1000];void addEdge(int from, int to, int cap) {    edges.push_back(Edge(from, to, cap, 0));    edges.push_back(Edge(to, from, 0, 0));    int i = edges.size();    G[from].push_back(i-2);    G[to].push_back(i-1);}int EK(int s, int t) {    int pre[1000]; //某点入弧号    int flow = 0;    int visit[1000]; //标记是否访问过以及起点到i的可改进量    while(1) {        memset(visit, 0, sizeof(visit));        queue<int> que;        que.push(s);        visit[s] = INF;        while(!que.empty()) {            int po = que.front();            que.pop();            for(int i = 0; i < G[po].size(); i++) {                Edge& ed = edges[G[po][i]];                if(!visit[ed.to] && ed.cap > ed.flow) {                    pre[ed.to] = G[po][i];                    visit[ed.to] = min(visit[po], ed.cap-ed.flow);                    que.push(ed.to);                }            }            if(visit[t])                break;        }        if(!visit[t])            break;        for(int i = t; i != s; i = edges[pre[i]].from) {            edges[pre[i]].flow += visit[t];            edges[pre[i]^1].flow -= visit[t];        }        flow += visit[t];    }    return flow;}int judge(string st) {    int j = 0;    int re;    for(int i = 1; i <= cou; i++) {        if(c[i] == st) {            re = i;            j = 1;            break;        }    }    if(j == 0) {        cou++;        c[cou] = st;        re = cou;    }    return re;}void input() {    memset(cg, 0, sizeof(cg));    memset(c, 0, sizeof(c));    cou = 0;    cin >> n;    for(int i = 1; i <= n; i++) {        string str;        cin >> str;        b[i] = judge(str);    }    cin >> m;    for(int i = 1; i <= m; i++) {        while(char ch = getchar()) {            if(ch == ' ')                break;        }        string str;        cin >> str;        a[i] = judge(str);    }    int k;    cin >> k;    for(int i = 1; i <= k; i++) {        string x, y;        cin >> x;        cin >> y;        int p = judge(x);        int q = judge(y);        cg[p][q] = 1;    }}void init() {    for(int i = 0; i <= m+n+1; i++)  {        G[i].clear();    }    edges.clear();    s = 0;    t = m + n + 1;    for(int k = 1; k <= cou; k++) {        for(int i = 1; i <= cou; i++)            for(int j = 1; j <= cou; j++) {                if(i == j)                    cg[i][j] = 1;                else if(cg[i][j] == 0 && cg[i][k] == 1 && cg[k][j] == 1) {                    cg[i][j] = 1;                }            }    }    for(int i = 1; i <= m; i++) {        addEdge(s, i, 1);    }    for(int i = m+1; i <= m+n; i++) {        addEdge(i, t, 1);    }    for(int j = 1; j <= n; j++) {        for(int i = 1; i <= m; i++) {            if(cg[a[i]][b[j]] == 1) {                addEdge(i, m+j, INF);            }        }    }}int main() {    int all;    cin >> all;    getchar();    while(all--) {        input();        init();        int result = m - EK(s, t);        cout << result << endl;        if(all) printf("\n");    }    return 0;}
原创粉丝点击