uva753

题目链接请戳 这里

 

解题思路

可以用最大流。

建立超级源点与每个设备连接,建立超级汇点与房间里有的插口连接。

至于适配器,注意有的接口房间里可能没有,要新建出来。连接直接在接口上连接,

不需要再建一个“适配器”顶点,因为这个顶点是可以忽略掉的(不清楚就画个图)。

注意适配器连接接口时,其容量为无穷,因为可以搞很多个适配器。其余的容量为1 。

还有,udebug上有个数据貌似是错了(不是uva的那个)。。。

 

代码

#include<iostream>
#include<string.h>
#include<string>
#include<queue>
#include<map>
#include<vector>
using namespace std;

const int N = 1010;
const int INF = 1e9;

int Flow[N][N], Cap[N][N];
int Pre[N];
int a[N];                //残量
map<string, int> V;      //顶点的编号
map<string, string> dv;  //设备与插口的映射
vector<string> sock;     //接口
bool can[N];             //房间里是否有某个接口
int n, m, k, vcnt;

int EK(int s, int t)
{
    queue<int> q;
    memset(Flow, 0, sizeof(Flow));
    int f = 0;
    while (1) {
        memset(a, 0, sizeof(a));
        a[s] = INF;
        q.push(s);
        while (!q.empty()) {
            int u = q.front(); q.pop();
            for (int v = s; v <= t; v++) if (!a[v] && Cap[u][v] > Flow[u][v]) {
                Pre[v] = u; q.push(v);
                a[v] = min(a[u], Cap[u][v] - Flow[u][v]);
            }
        }
        if (a[t] == 0) break;
        for (int u = t; u != s; u = Pre[u]) {
            Flow[Pre[u]][u] += a[t];
            Flow[u][Pre[u]] -= a[t];
        }
        f += a[t];
    }
    return f;
}
int main()
{
    int tests;
    cin >> tests;
    while (tests--) {
        //记得要初始化哟
        memset(Cap, 0, sizeof(Cap));
        memset(can, 0, sizeof(can));
        sock.clear(); V.clear(); dv.clear();
        vcnt = 0;        //顶点数
        cin >> n;
        for (int i = 0; i < n; i++) {
            string s;
            cin >> s;
            can[s.front()] = true;    //房间里有这个接口
            sock.push_back(s);        //接口加入到vector中,有重复也没关系
        }
        cin >> m;
        for (int i = 0; i < m; i++) {
            string s1, s2;
            cin >> s1 >> s2;
            dv[s1] = s2;              //设备与接口的映射
            V[s1] = ++vcnt;           //给设备编号
            sock.push_back(s2);       //接口加入到vector中
            Cap[0][V[s1]] = 1;        //超级源与设备连接
        }
        //为收集到的接口编号
        int len = sock.size();
        for (int i = 0; i < len; i++) if(V.find(sock[i]) == V.end()){
            V[sock[i]] = ++vcnt;
        }
        //适配器连接,注意容量为无穷
        cin >> k;
        for (int i = 0; i < k; i++) {
            string s1, s2;
            cin >> s1 >> s2;
            Cap[V[s1]][V[s2]] = INF;
        }
        //超级汇与接口连接
        vcnt++;
        for (int i = 0; i < len; i++) if(can[sock[i][0]])  //注意只有房间有的接口才能与汇点连接
            Cap[V[sock[i]]][vcnt] = 1;
        //设备与接口连接
        map<string, string>::iterator iter;
        for (iter = dv.begin(); iter != dv.end(); iter++) {
            Cap[V[iter->first]][V[iter->second]] = 1;
        }
        //计算最大流
        int left = m - EK(0, vcnt);
        cout << left << endl;
        //最后一个测试不输出换行
        if (tests) cout << endl;
    }
    return 0;
}

 

posted @ 2016-10-29 11:37  啊嘞  阅读(231)  评论(0编辑  收藏  举报