• POJ3189二分最大流(枚举下界,二分宽度,最大流判断可行性)


    题意:
          有n头猪,m个猪圈,每个猪圈都有一定的容量(就是最多能装多少只猪),然后每只猪对每个猪圈的喜好度不同(就是所有猪圈在每个猪心中都有一个排名),然后要求所有的猪都进猪圈,但是要求所有的喜好度排名最低的和最高的差值的绝对值最小,输出这个最小的差值,就是是每个猪进猪圈后都会产生一个范围,就是最喜欢和最不喜欢(用排名的名次表示),然后把所有的范围放在一起,最小的端点个最大的端点的差的绝对值最小是多少?


    思路:
           做了将近两个小时才搞定,一直是超时,先说下我的做法,就是枚举下界,二分答案,然后DINIC判断是否可行,用G++交跑100+ms,用C++交超时,还有一个目测比较快的方法,就是把上面的DINIC换成多重匹配,多重匹配处理二分图的时候比DINIC快,所以理论上更优,可惜我没写过多重匹配,这个会的可以试试,最后我用匈牙利,然后暴力拆点去模拟多重匹配,超时了,呵呵,下面是我一开始最笨的方法,枚举下界+二分答案+DINIC判断可行性的代码,还有就是提醒下,输入的时候那个排名什么的要看清楚,就是读懂输入,嘿嘿别的没啥。




    用G++提交
    枚举起点,二分长度,最大流判断可行。
    #include<queue>
    #include<stdio.h>
    #include<string.h>


    #define N_node 1000 + 20 + 5
    #define N_edge (1000 * 20 + 1000 + 20) * 2 + 5000
    #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;
    int list[N_node] ,listt[N_node] ,tot;
    int deep[N_node];
    int Sort[1005][22];
    int Cow[22];
    int ANS ,N;




    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;
        deep[xin.x] = xin.t;
        queue<DEP>q;
        q.push(xin);
        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;
            int c = E[k].cost;
            if(deep[to] != deep[s] + 1 || !c)
            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);
            if(Ans == N) break;
        }
        return Ans;
    }


    void Buid(int n ,int m ,int a ,int b)
    {
        memset(list ,0 ,sizeof(list));
        tot = 1;
        for(int i = 1 ;i <= n ;i ++)
        add(0 ,i ,1);
        for(int i = 1 ;i <= m ;i ++)
        add(i + n ,m + n + 1 ,Cow[i]);
        for(int i = 1 ;i <= n ;i ++)
        for(int j = 1 ;j <= m ;j ++)
        if(Sort[i][j] >= a && Sort[i][j] <= b)
        add(i ,j + n ,1);
    }


    int solve(int n ,int m ,int ii)
    {
        int low = 0 ,up = m - ii ,mid ,Ans = INF;
        if(up > ANS) up = ANS;
        while(low <= up)
        {
            mid = (low + up) >> 1;
            Buid(n ,m ,ii ,ii + mid);
            if(DINIC(0 ,n + m + 1 ,n + m + 1) == n)
            {
                Ans = mid;
                up = mid - 1;
            }
            else low = mid + 1;
        }
        return Ans;
    }


    int main ()
    {
        int n ,m ,i ,j ,a;
        while(~scanf("%d %d" ,&n ,&m))
        {
            N = n;
            for(i = 1 ;i <= n ;i ++)
            for(j = 1 ;j <= m ;j ++)
            {
                scanf("%d" ,&a);
                Sort[i][a] = j;
            }
            for(i = 1 ;i <= m ;i ++)
            scanf("%d" ,&Cow[i]);
            ANS = INF;
            for(i = 1 ;i <= m ;i ++)
            {
                ANS = minn(ANS ,solve(n ,m ,i));
            }
            printf("%d " ,ANS + 1);
        }
        return 0;
    }







  • 相关阅读:
    华为笔试
    进程间通信——管道通信
    进程间通信——使用WM_COPYDATA消息通信
    混合高斯背景建模
    基于mean shift的目标跟踪算法
    Lukas-Kanade光流法
    【CUDA并行编程之八】Cuda实现Kmeans算法
    【CUDA并行编程之七】数组元素之和
    【CUDA并行编程之六】KNN算法的并行实现
    【CUDA并行编程之五】计算向量的欧式距离
  • 原文地址:https://www.cnblogs.com/csnd/p/12062463.html
Copyright © 2020-2023  润新知