• POJ-1087 A Plug for UNIX


    题目链接:POJ-1087 A Plug for UNIX

    题意

    有$n$个插座,m个用电器,每个用电器都对应一个插头(插头类型与插座相同则可插入充电),$k$种转换器(每种数量无限),$s_1$ $s_2$表示一个$s_2$类型插座可以转换成一个$s_1$类型插座,问最少有几个用电器无法同时充电。


    思路

    可建图用最大流求解,源点指向$n$个插座,$m$个用电器指向汇点,插座指向对应的用电器,容量均为1,对于一个转换器$(s_1,s_2)$,插座$s_2$指向$s_1$,容量为无穷大。最大流表示可同时充电的最大充电器数量,用$m$减去最大流即为答案。


    代码实现

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <string>
    #include <queue>
    #include <map>
    using std::queue;
    using std::map;
    using std::cin;
    using std::cout;
    using std::endl;
    using std::string;
    const int INF = 0x3f3f3f3f, N = 500, M = 1000;
    int head[N], d[N];
    int s, t, tot, maxflow;
    struct Edge
    {
        int to, cap, nex;
    } edge[M];
    queue<int> q;
    void add(int x, int y, int z) {
        edge[++tot].to = y, edge[tot].cap = z, edge[tot].nex = head[x], head[x] = tot;
        edge[++tot].to = x, edge[tot].cap = 0, edge[tot].nex = head[y], head[y] = tot;
    }
    bool bfs() {
        memset(d, 0, sizeof(d));
        while (q.size()) q.pop();
        q.push(s); d[s] = 1;
        while (q.size()) {
            int x = q.front(); q.pop();
            for (int i = head[x]; i; i = edge[i].nex) {
                int v = edge[i].to;
                if (edge[i].cap && !d[v]) {
                    q.push(v);
                    d[v] = d[x] + 1;
                    if (v == t) return true;
                }
            }
        }
        return false;
    }
    int dinic(int x, int flow) {
        if (x == t) return flow;
        int rest = flow, k;
        for (int i = head[x]; i && rest; i = edge[i].nex) {
            int v = edge[i].to;
            if (edge[i].cap && d[v] == d[x] + 1) {
                k = dinic(v, std::min(rest, edge[i].cap));
                if (!k) d[v] = 0;
                edge[i].cap -= k;
                edge[i^1].cap += k;
                rest -= k;
            }
        }
        return flow - rest;
    }
    void init() {
        tot = 1, maxflow = 0;
        s = 0, t = 1;
        memset(head, 0, sizeof(head));
    }
    
    int main() {
        int n, m, k;
        while (cin >> n) {
            init();
            int idx = 1;
            string s1, s2;
            map<string, int> mp;
            for (int i = 0; i < n; i++) {
                cin >> s1;
                if (!mp[s1]) mp[s1] = ++idx;
                add(0, mp[s1], 1);
            }
            cin >> m;
            for (int i = 0; i < m; i++) {
                cin >> s1 >> s2;
                if (!mp[s1]) mp[s1] = ++idx;
                if (!mp[s2]) mp[s2] = ++idx;
                add(mp[s2], mp[s1], 1);
                add(mp[s1], 1, 1);
            }
            cin >> k;
            for (int i = 0; i < k; i++) {
                cin >> s1 >> s2;
                if (!mp[s1]) mp[s1] = ++idx;
                if (!mp[s2]) mp[s2] = ++idx;
                add(mp[s2], mp[s1], INF);
            }
            while (bfs()) maxflow += dinic(s, INF);
            cout << (m - maxflow) << endl;
        }
        return 0;
    }
    View Code
    作者:_kangkang
    本文版权归作者和博客园共有,欢迎转载,但必须给出原文链接,并保留此段声明,否则保留追究法律责任的权利。
  • 相关阅读:
    Inno Setup入门(六)——在程序目录下创建文件
    Inno Setup入门(五)——添加readme文件
    Inno Setup入门(四)——为程序创建桌面快捷方式
    Inno Setup入门(三)——指定压缩方式
    Inno Setup入门(二)——修改安装过程中的图片
    61 origin授控于MATLAB
    origin里用c语言编程
    flac3d自定义变量输出云图
    C语言学生管理系统源码分享
    c语言学生信息管理系统-学习结构体
  • 原文地址:https://www.cnblogs.com/kangkang-/p/11321912.html
Copyright © 2020-2023  润新知