zoukankan      html  css  js  c++  java
  • poj1087 A Plug for UNIX(网络流最大流)

    http://poj.org/problem?id=1087

      好久没遇见过这么坑的题了这个题真是挫的够可以的。题目大意:你作为某高管去住宿了,然后宾馆里有几种插座,分别有其对应型号,你携带了几种用电器(手机,电脑一类的),

    也有其对应型号;可是不一定用电器就能和插座匹配上,于是宾馆的商店里提供了一些转换器,这些转换器可以将某一型号电源转换成另一型号的。问,你的用电器最少会有多少种无

    法充电。也就是问可以用上电的用电器的最大数目,之后用电器总数减去此可用电最大数目即可得到最小不能用电数目。

      一开始以为直接将插座,转换器,用电器匹配后跑个最大流模板就行,后来发现想的太简单了。

      分析:

      1:用电器可直接连插座;

      2:用电器可以连接转换器再连接上插座;

      3:转换器之间可以相互连接;

      4:转换器转换作用是双向的,比如给定转换器可对A和B进行转换,则此转换器可以将A转换成B,也可以将B转换成A;

      5:每种转换器的数目是无限的;

      6:一个插座只能连接产生一个出处。

      7:虚拟一个源点一个汇点即可,源点到插座和插头到汇点的流量为1。

    按照这些建图失误了四次之后终于成功A过了。

    附加详细建图步骤的备注的AC代码和一组测试数据(测试答案应当为0)

    #include <stdio.h>
    #include <algorithm>
    #include <string.h>
    #include <queue>
    using namespace std;
    #define oo 0x3f3f3f3f
    int G[1000][1000], n, m, p, vis[1000];
    char receptacle[500][30];
    char plug[500][30];
    struct ad
    {
        char in[30], out[30];
    }adapter[500];
    
    bool bfs(int Start, int End)
    {
        memset(vis, 0, sizeof(vis));
        vis[Start] = 1;
    
        queue<int>Q;
        Q.push(Start);
    
        while(Q.size())
        {
            int now = Q.front();
            Q.pop();
    
            if(now == End)
                return true;
    
            for(int i=1; i<=End; i++)
            {
                if(!vis[i] && G[now][i]>0)
                {
                    vis[i] = vis[now] + 1;
                    Q.push(i);
                }
            }
        }
    
        return false;
    }
    
    
    int dfs(int Start, int End, int Maxflow)
    {
        if(Start == End)
            return Maxflow;
    
        int nowflow = 0;
    
        for(int i=1; i<=End; i++)
        {
            if(vis[i] == vis[Start] + 1 && G[Start][i]>0)
            {
                int flow = min(G[Start][i], Maxflow - nowflow);
    
                flow = dfs(i, End, flow);
    
                G[Start][i] -= flow;
                G[i][Start] += flow;
    
                nowflow += flow;
    
                if(nowflow == Maxflow)
                    break;
            }
        }
    
        return nowflow;
    }
    int dinic(int Start, int End)
    {
        int ans = 0, s;
    
        while(bfs(Start, End))
        {
            s = dfs(Start, End, oo);
            if(!s)break;
            ans += s;
        }
    
        return ans;
    }
    int main()
    {
        while(~scanf("%d", &n))
        {
            memset(G, 0, sizeof(G));
    
            for(int i=1; i<=n; i++)
                scanf("%s", receptacle[i]);
    
            scanf("%d", &m);
            for(int i=1; i<=m; i++)
            {
                scanf("%*s %s", plug[i]);
                for(int j=1; j<=n; j++)
                {
                    if(strcmp(receptacle[j], plug[i]) == 0)///插头和插座可直接连
                    {
                        G[j][n+p+i] = 1;
                    }
                }
            }
    
            scanf("%d", &p);
            for(int i=1; i<=p; i++)
                scanf("%s %s", adapter[i].in, adapter[i].out);
    
    
    
            for(int i=1; i<=p; i++)///1~n是插座,n+1~n+p是转换器,n+p+1~n+p+m是插头
            {
                for(int j=1; j<=n; j++)
                {
                    if(strcmp(receptacle[j], adapter[i].in)==0 || strcmp(receptacle[j], adapter[i].out)==0)///插座和转换器匹配
                    {
                        G[j][n+i] = 1;
                    }
                }
    
                for(int j=1; j<=m; j++)
                {
                    if(strcmp(plug[j], adapter[i].out)==0 || strcmp(plug[j], adapter[i].in)==0)///转换器和插头匹配
                    {
                        G[n+i][n+p+j] = 1;
                    }
                }
            }
    
            for(int i=1; i<=p; i++)///转换器之间相连
            {
                for(int j=1; j<=p; j++)
                {
                    if(i!=j && strcmp(adapter[i].in, adapter[j].out)==0)
                        G[n+i][n+j] = oo;
                }
                for(int j=1; j<=p; j++)
                {
                    if(i!=j && strcmp(adapter[i].out, adapter[j].in)==0)
                        G[n+i][n+j] = oo;
                }
            }
    
    
            int Start = n+p+m+1, End = Start+1;
    
            for(int i=1; i<=n; i++)///源点和插座相连
            {
                G[Start][i] = 1;
            }
    
            for(int i=1; i<=m; i++)///插头和汇点相连
            {
                G[n+p+i][End] = 1;
            }
    
            printf("%d
    ", m - dinic(Start, End));
        }
        return 0;
    }
    
    /*
    16
    A
    D
    X
    A
    D
    A
    D
    X
    D
    A
    D
    D
    X
    D
    X
    D
    14
    CLOCK B
    CLOCK B
    CLOCK B
    LAPTOP B
    LAPTOP B
    LAPTOP B
    LAPTOP B
    LAPTOP B
    LAPTOP B
    PAGER B
    PAGER B
    COMB X
    CELL C
    CELL C
    4
    C D
    X D
    B X
    B A
    */
  • 相关阅读:
    (转)用stunnel给普通http通信加密
    (原)logstash-forwarder + logstash + elasticsearch + kibana
    nsq初探
    (转)go语言nsq源码解读二 nsqlookupd、nsqd与nsqadmin
    (转)Linux下的输入/输出重定向
    (转) Lua: 给 Redis 用户的入门指导
    Android ——多线程处理之多线程用法大集合(转)
    Android——线程通讯类Handler(转)
    Android—— 线程 thread 两种实现方法!(转)
    Android-——多线程之Handler(转)
  • 原文地址:https://www.cnblogs.com/zznulw/p/5929247.html
Copyright © 2011-2022 走看看