hdu 3189(网络流+二分枚举)

Steady Cow Assignment

Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions: 6422   Accepted: 2202

Description

Farmer John‘s N (1 <= N <= 1000) cows each reside in one of B (1 <= B <= 20) barns which, of course, have limited capacity. Some cows really like their current barn, and some are not so happy.

FJ would like to rearrange the cows such that the cows are as
equally happy as possible, even if that means all the cows hate their
assigned barn.

Each cow gives FJ the order in which she prefers the barns. A cow‘s
happiness with a particular assignment is her ranking of her barn. Your
job is to find an assignment of cows to barns such that no barn‘s
capacity is exceeded and the size of the range (i.e., one more than the
positive difference between the the highest-ranked barn chosen and that
lowest-ranked barn chosen) of barn rankings the cows give their assigned
barns is as small as possible.

Input

Line 1: Two space-separated integers, N and B

Lines 2..N+1: Each line contains B space-separated integers which
are exactly 1..B sorted into some order. The first integer on line i+1
is the number of the cow i‘s top-choice barn, the second integer on that
line is the number of the i‘th cow‘s second-choice barn, and so on.

Line N+2: B space-separated integers, respectively the capacity of
the first barn, then the capacity of the second, and so on. The sum of
these numbers is guaranteed to be at least N.

Output

Line 1: One integer, the size of the minumum range of barn rankings the cows give their assigned barns, including the endpoints.

Sample Input

6 4
1 2 3 4
2 3 1 4
4 2 3 1
3 1 2 4
1 3 4 2
1 4 2 3
2 1 3 2

Sample Output

2

Hint

Explanation of the sample:

Each cow can be assigned to her first or second choice: barn 1 gets
cows 1 and 5, barn 2 gets cow 2, barn 3 gets cow 4, and barn 4 gets cows
3 and 6.

这个题看懂题目才是关键啊。。。错了n多次.

题意:有n头牛b个牛栏,每头牛对每个牛栏有一个满意度,每个牛栏有一个容量,输入n,b 然后输入的矩阵(i,j)代表的是第i头牛第j满意的是牛栏是 g[i][j] 。。就是这句话要看懂,然后最大满意度与最小满意度差值最小是多少(注意此处差值 = MAX-MIN+1).

题解:看懂题后就容易了,构图的话就是建立超级源点S,S向每个牛栏建容量为牛栏容量的单向边,每头牛向超级汇点T连一条容量为1的边,然后枚举差值,当差值为刚好让最大流为n的时候就得到了满足条件的最小差值。

#include <stdio.h>
#include <algorithm>
#include <queue>
#include <string.h>
#include <math.h>
#include <iostream>
#include <math.h>
using namespace std;
const int N = 1100;
const int INF = 999999999;
struct Edge{
    int v,next;
    int w;
}edge[N*N];
struct Cow{
    int love[25];
}cow[N];
int head[N];
int level[N];
int graph[N][N],dis[N][N],cap[N];
int tot;
void init(){
    memset(head,-1,sizeof(head));
    tot=0;
}
void addEdge(int u,int v,int w,int &k){
    edge[k].v = v,edge[k].w=w,edge[k].next=head[u],head[u]=k++;
    edge[k].v = u,edge[k].w=0,edge[k].next=head[v],head[v]=k++;
}
int BFS(int src,int des){
    queue<int >q;
    memset(level,0,sizeof(level));
    level[src]=1;
    q.push(src);
    while(!q.empty()){
        int u = q.front();
        q.pop();
        if(u==des) return 1;
        for(int k = head[u];k!=-1;k=edge[k].next){
            int v = edge[k].v;
            int w = edge[k].w;
            if(level[v]==0&&w!=0){
                level[v]=level[u]+1;
                q.push(v);
            }
        }
    }
    return -1;
}
int dfs(int u,int des,int increaseRoad){
    if(u==des) return increaseRoad;
    int ret=0;
    for(int k=head[u];k!=-1;k=edge[k].next){
        int v = edge[k].v;
        int w = edge[k].w;
        if(level[v]==level[u]+1&&w!=0){
            int MIN = min(increaseRoad-ret,w);
            w = dfs(v,des,MIN);
            if(w>0){
            edge[k].w -=w;
            edge[k^1].w+=w;
            ret+=w;
            if(ret==increaseRoad) return ret;
            }else level[v] = -1;
        }
    }
    return ret;
}
int Dinic(int src,int des){
    int ans = 0;
    while(BFS(src,des)!=-1) ans+=dfs(src,des,INF);
    return ans;
}
int n,b,src,des;
int build(int t,int mid){
    init();
    for(int i=1;i<=b;i++){
        addEdge(src,i,cap[i],tot);
    }
    for(int i=1;i<=n;i++){
        addEdge(i+b,des,1,tot);
    }
    for(int i=t;i<=t+mid-1&&i<=b;i++){
        for(int j=1;j<=n;j++){
            addEdge(cow[j].love[i],j+b,1,tot);
        }
    }
    return Dinic(src,des);
}
int main(){
    scanf("%d%d",&n,&b);
    src = 0,des = n+b+1;
    for(int i=1;i<=n;i++){
        for(int j=1;j<=b;j++){
            scanf("%d",&cow[i].love[j]);
        }
    }
    for(int i=1;i<=b;i++) scanf("%d",&cap[i]);
    int l =0,r = b;
    int ans = b;
    while(l<=r){
        int mid = (l+r)>>1;  ///差值
        bool flag = false;
        for(int i=1;i<=b;i++){ ///枚举最小值
            if(build(i,mid)==n) {
                flag = 1;
                break;
            }
        }
        if(flag) {
            ans = mid;
            r = mid-1;
        }else l = mid+1;
    }
    printf("%d\n",ans);
}
时间: 2024-10-12 21:23:36

hdu 3189(网络流+二分枚举)的相关文章

HDU 5371 (2015多校联合训练赛第七场1003)Hotaru&#39;s problem(manacher+二分/枚举)

HDU 5371 题意: 定义一个序列为N序列:这个序列按分作三部分,第一部分与第三部分相同,第一部分与第二部分对称. 现在给你一个长为n(n<10^5)的序列,求出该序列中N序列的最大长度. 思路: 来自官方题解:修正了一些题解错别字(误 先用求回文串的Manacher算法,求出以第i个点为中心的回文串长度,记录到数组p中 要满足题目所要求的内容,需要使得两个相邻的回文串,共享中间的一部分,也就是说,左边的回文串长度的一半,要大于等于共享部分的长度,右边回文串也是一样. 因为我们已经记录下来以

HDU 5371 (2015多校联合训练赛第七场1003)Hotaru&amp;#39;s problem(manacher+二分/枚举)

pid=5371">HDU 5371 题意: 定义一个序列为N序列:这个序列按分作三部分,第一部分与第三部分同样,第一部分与第二部分对称. 如今给你一个长为n(n<10^5)的序列,求出该序列中N序列的最大长度. 思路: 来自官方题解:修正了一些题解错别字(误 先用求回文串的Manacher算法.求出以第i个点为中心的回文串长度.记录到数组p中 要满足题目所要求的内容.须要使得两个相邻的回文串,共享中间的一部分,也就是说.左边的回文串长度的一半,要大于等于共享部分的长度,右边回文串也

HDU 4430 &amp; ZOJ 3665 Yukari&#39;s Birthday(二分+枚举)

题目链接: HDU:http://acm.hdu.edu.cn/showproblem.php?pid=4430 ZJU:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=4888 Problem Description Today is Yukari's n-th birthday. Ran and Chen hold a celebration party for her. Now comes the most import

HDU 3036 Escape 网格图多人逃生 网络流||二分匹配 建图技巧

前言 在编程过程中总结归纳出来的一种编程经验,从而形成的设计思想称为设计模式. 设计模式有23种.它适用于所有的编程语言. 常用的有创新型的设计模式:简单工厂.抽象工厂和单例模式:行为型的设计模式:模板设计模式.观察者模式和命令模式:结构性的设计模式:适配器设计模式.代理模式(静态和动态两种,典型的有在spring的AOP编程中使用)和装饰器设计模式. 正文 单例模式(singleton) 保证一个类在内存中只能创建一个实例. 1.实现步骤: 1)将构造器私有化,即使用private修饰构造器

hdu 3277 Marriage Match III【最大流+并查集+二分枚举】

Marriage Match III Time Limit: 10000/4000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 1491    Accepted Submission(s): 440 Problem Description Presumably, you all have known the question of stable marriage match.

hdu 5248 序列变换(二分枚举)

Problem Description 给定序列A={A1,A2,...,An}, 要求改变序列A中的某些元素,形成一个严格单调的序列B(严格单调的定义为:Bi<Bi+1,1≤i<N). 我们定义从序列A到序列B变换的代价为cost(A,B)=max(|Ai−Bi|)(1≤i≤N). 请求出满足条件的最小代价. 注意,每个元素在变换前后都是整数. Input 第一行为测试的组数T(1≤T≤10). 对于每一组: 第一行为序列A的长度N(1≤N≤105),第二行包含N个数,A1,A2,...,A

POJ 2455--Secret Milking Machine【二分枚举 &amp;&amp; 最大流 &amp;&amp; 经典】

Secret Milking Machine Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 10625   Accepted: 3111 Description Farmer John is constructing a new milking machine and wishes to keep it secret as long as possible. He has hidden in it deep within

HDU 3488Tour(网络流之最小费用流)

题目地址:hdu3488 这题跟上题基本差不多啊....详情请戳这里. 另外我觉得有要改变下代码风格了..终于知道了为什么大牛们的代码的变量名都命名的那么长..我决定还是把源点与汇点改成source和sink吧..用s和t太容易冲突了...于是如此简单的一道题调试到了现在..sad... 代码如下: #include <iostream> #include <stdio.h> #include <string.h> #include <stdlib.h> #

【noi 2.2_7891】一元三次方程求解(二分枚举)

对于noi上的题有2中解法: 1.数据很小(N=100),可以直接打for循环枚举和判断. 2.不会“三分”,便用二分.利用“两根相差>=1”和 f(x1)*f(x2)<0,转换意思为[x,x+1]内不会包含两个根,这样枚举可以保证不漏解.因此,枚举一个个根所在的区间,再用二分枚举找出根.其中,若N=10^5,由于保留2位小数,最好精确到4位小数计算.时间复杂度 O(N)=10^5+3*log(10^4),约为10^5. 以下附上二分的代码—— 1 //20160908 Ann 2 #incl