zoukankan      html  css  js  c++  java
  • POJ1087DFS+匈牙利或者DINIC

    题意:
         有n个插孔,m个电器,q种转换器(转换器可以无限用),然后问你最多有多少个电器能充电。


    思路:
          比较简单,就是在建图的时候要考虑下,我用了两种方法做的,一个是最大流,这个方法我的建图是这样,先给每个用电器虚拟出来一个点n,每个插座虚拟出来两个点(限流)m,然后给每个插座或者是插头的类型虚拟出来一个点,这样就ok了,建图是这样
    s         -> 所有用电器       1
    所有用电器->他所连接的种类    1
    种类      ->种类             INF   这个是转换器
    种类      ->插座              1
    插座到    ->插座              1    限流
    插座      -> t                1
    然后一遍s到t的最大流


    另一种方法是用二分匹配,这个方法我们可以这样想,建立二分图,左边是用电器,右边是插座,然后用电器和插座能连的条件是可以直接或者间接连接上,这个地方可以用搜索搞定,这样在处理所有连接关系的时候的时间复杂度一共是n^2的,一开始想用Floyd了,考虑到那样的话最坏的情况会达到500*500*500就没用,通过搜索建立间接之后就可以直接匈牙利匹配了,下面是两种方法的代码。




    DINIC
    #include<map>
    #include<queue>
    #include<stdio.h>
    #include<string>
    #include<string.h>


    #define N_node 700 + 10
    #define N_edge 700 * 700 + 50
    #define INF 1000000000


    using namespace std;


    typedef struct
    {
        int to ,cost ,next;
    }STAR;


    typedef struct
    {
        int x ,t;
    }DEP;


    STAR E[N_edge];
    DEP xin ,tou;
    map<string ,int>mark;
    int deep[N_node];
    int list[N_node] ,listt[N_node] ,tot;


    void add(int a ,int b ,int c)
    {
        E[++tot].to = b;
        E[tot].cost = c;
        E[tot].next = list[a];
        list[a] = tot;


        E[++tot].to = a;
        E[tot].cost = 0;
        E[tot].next = list[b];
        list[b] = tot;
    }


    int minn(int x ,int y)
    {
        return x < y ? x : y;
    }


    bool BFS_DEEP(int s ,int t ,int n)
    {
        memset(deep ,255 ,sizeof(deep));
        xin.x = s ,xin.t = 0;
        queue<DEP>q;
        q.push(xin);
        deep[s] = 0;
        while(!q.empty())
        {
            tou = q.front();
            q.pop();
            for(int k = list[tou.x] ;k ;k = E[k].next)
            {
                xin.x = E[k].to;
                xin.t = tou.t + 1;
                if(deep[xin.x] != -1 || !E[k].cost)
                continue;
                deep[xin.x] = xin.t;
                q.push(xin);
            }
        }
        for(int i = 0 ;i <= n ;i ++)
        listt[i] = list[i];
        return deep[t] != -1;
    }




    int DFS_Flow(int s ,int t ,int flow)
    {
        if(s == t) return flow;
        int nowflow = 0;
        for(int k = listt[s] ;k ;k = E[k].next)
        {
            listt[s] = k;
            int to = E[k].to ,c = E[k].cost;
            if(!c || deep[to] != deep[s] + 1)
            continue;
            int tmp = DFS_Flow(to ,t ,minn(c ,flow - nowflow));
            nowflow += tmp;
            E[k].cost -= tmp;
            E[k^1].cost += tmp;
            if(flow == nowflow)
            break;
        }
        if(!nowflow) deep[s] = 0;
        return nowflow;
    }


    int DINIC(int s ,int t ,int n)
    {
        int ans = 0;
        while(BFS_DEEP(s ,t ,n))
        {
            ans += DFS_Flow(s ,t ,INF);
        }
        return ans;
    }


    int main ()
    {
        int n ,m ,q ,i;
        char str1[25+5] ,str2[25+5];
        while(~scanf("%d" ,&n))
        {
            memset(list ,0 ,sizeof(list));
            tot = 1;
            mark.clear();
            int nowid = 0;
            int s = 0 ,t = 705;
            for(i = 1 ;i <= n ;i ++)
            {
                scanf("%s" ,str1);
                if(!mark[str1]) mark[str1] = ++nowid;
                add(mark[str1] + 200 ,mark[str1] + 600 ,1);
                add(mark[str1] + 600 ,i + 100 ,1);
                add(i + 100 ,t ,1);
            }
            scanf("%d" ,&m);
            for(i = 1 ;i <= m ;i ++)
            {
                scanf("%s %s" ,str1 ,str2);
                if(!mark[str2]) mark[str2] = ++nowid;
                add(s ,i ,1);
                add(i ,mark[str2] + 200 ,1);
            }
            scanf("%d" ,&q);
            for(i = 1 ;i <= q ;i ++)
            {
                scanf("%s %s" ,str1 ,str2);
                if(!mark[str1]) mark[str1] = ++nowid;
                if(!mark[str2]) mark[str2] = ++nowid;
                add(mark[str1] + 200 ,mark[str2] + 200 ,INF);
            }
            printf("%d " ,m - DINIC(s ,t ,705));
        }
        return 0;
    }


    匈牙利+DFS
    #include<map>
    #include<stdio.h>
    #include<string>
    #include<string.h>


    #define N_node 500
    #define N_edge 500 * 500 + 10
    #define INF 100000000


    using namespace std;


    typedef struct
    {
        int to ,next;
    }STAR;


    STAR E[N_edge];
    int mkdfs[N_node] ,mkgx[N_node];
    int list[N_node] ,tot;
    int _map[N_node][N_node];
    int cz[N_node] ,dq[N_node];
    map<string ,int>mark;


    void add(int a ,int b)
    {
        E[++tot].to = b;
        E[tot].next = list[a];
        list[a] = tot;
    }


    void DFS(int s ,int now)
    {
        for(int k = list[now] ;k ;k = E[k].next)
        {
            int to = E[k].to;
            if(mkdfs[to]) continue;
            mkdfs[to] = _map[s][to] = 1;
            DFS(s ,to);
        }
        return ;
    }


    int DFS_XYL(int x)
    {
        for(int k = list[x] ;k ;k = E[k].next)
        {
            int to = E[k].to;
            if(mkdfs[to]) continue;
            mkdfs[to] = 1;
            if(mkgx[to] == -1 || DFS_XYL(mkgx[to]))
            {
                mkgx[to] = x;
                return 1;
            }
        }
        return 0;
    }


    int main ()
    {
        int n ,m ,q ,i ,j ,a ,b;
        char str1[30] ,str2[30];
        while(~scanf("%d" ,&n))
        {
            mark.clear();
            int nowid = 0;
            for(i = 1 ;i <= n ;i ++)
            {
                scanf("%s" ,str1);
                if(!mark[str1]) mark[str1] = ++nowid;
                cz[i] = mark[str1];
            }
            scanf("%d" ,&m);
            for(i = 1 ;i <= m ;i ++)
            {
                scanf("%s %s" ,str1 ,str2);
                if(!mark[str2]) mark[str2] = ++nowid;
                dq[i] = mark[str2];
            }
            memset(list ,0 ,sizeof(list));
            tot = 1;
            scanf("%d" ,&q);
            for(i = 1 ;i <= q ;i ++)
            {
                scanf("%s %s" ,str1 ,str2);
                if(!mark[str1]) mark[str1] = ++nowid;
                if(!mark[str2]) mark[str2] = ++nowid;
                add(mark[str1] ,mark[str2]);
            }
            memset(_map ,0 ,sizeof(_map));
            for(i = 1 ;i <= nowid ;i ++)
            {
                memset(mkdfs ,0 ,sizeof(mkdfs));
                _map[i][i] = 1;
                DFS(i ,i);
            }
            memset(list ,0 ,sizeof(list));
            tot = 1;
            for(i = 1 ;i <= m ;i ++)
            for(j = 1 ;j <= n ;j ++)
            if(_map[dq[i]][cz[j]]) add(i ,j);
            int ans = 0;
            memset(mkgx ,255 ,sizeof(mkgx));
            for(i = 1 ;i <= nowid ;i ++)
            {
                memset(mkdfs ,0 ,sizeof(mkdfs));
                ans += DFS_XYL(i);
            }
            printf("%d " ,m - ans);
        }
        return 0;
    }















  • 相关阅读:
    mysql 覆盖索引
    mysql 连接查询 和 子查询
    mysql varchar
    uchome 是如何将数据插入数据库的
    Tomcat5 在windows安装服务
    Linux中错误码及描述查看
    Longines浪琴手表型号解释
    perl 安装 Net::Telnet 模块
    php一些错误的显示问题
    firefox样式表cursor和兼容Ie firefox,解决文字溢出的问题(wordwrap:breakword;wordbreak:breakall)
  • 原文地址:https://www.cnblogs.com/csnd/p/12062526.html
Copyright © 2011-2022 走看看