zoukankan      html  css  js  c++  java
  • 【bzoj1532】[POI2005]Kos-Dicing 二分+网络流最大流

    题目描述

    Dicing 是一个两人玩的游戏,这个游戏在Byteotia非常流行. 甚至人们专门成立了这个游戏的一个俱乐部. 俱乐部的人时常在一起玩这个游戏然后评选出玩得最好的人.现在有一个非常不走运的家伙,他想成为那个玩的最好的人,他现在知道了所有比赛的安排,他想知道,在最好的情况下,他最少只需要赢几场就可以赢得冠军,即他想知道比赛以后赢的最多的那个家伙最少会赢多少场.

    输入

    第一行两个整数n 和 m, 1 <= n <= 10 000, 0 <= m <= 10 000; n 表示一共有多少个参赛者, m 表示有多少场比赛. 选手从1 到 n编号. 接下来m 行每行两个整数表示该场比赛的两个选手,两个选手可能比赛多场.

    输出

    第一行表示赢得最多的人最少会赢多少场

    样例输入

    4 4
    1 2
    1 3
    1 4
    1 2

    样例输出

    1


    题解

    二分+网络流最大流

    显然答案是可以二分的,所以我们可以二分mid,问题就转变为:每个人最多赢mid场,问能否完成所有比赛。

    连边S->每场比赛,容量为1;每场比赛->对应的两个参赛的人,容量为1;每个人->T,容量为mid。

    跑最大流,判断是否满流并调整边界,得到答案。

    #include <cstdio>
    #include <cstring>
    #include <queue>
    #define N 20010
    #define M 150010
    using namespace std;
    queue<int> q;
    int n , m , x[N] , y[N] , head[N] , to[M] , val[M] , next[M] , cnt , s , t , dis[N];
    void add(int x , int y , int z)
    {
    	to[++cnt] = y , val[cnt] = z , next[cnt] = head[x] , head[x] = cnt;
    	to[++cnt] = x , val[cnt] = 0 , next[cnt] = head[y] , head[y] = cnt;
    }
    bool bfs()
    {
    	int x , i;
    	memset(dis , 0 , sizeof(dis));
    	while(!q.empty()) q.pop();
    	dis[s] = 1 , q.push(s);
    	while(!q.empty())
    	{
    		x = q.front() , q.pop();
    		for(i = head[x] ; i ; i = next[i])
    		{
    			if(val[i] && !dis[to[i]])
    			{
    				dis[to[i]] = dis[x] + 1;
    				if(to[i] == t) return 1;
    				q.push(to[i]);
    			}
    		}
    	}
    	return 0;
    }
    int dinic(int x , int low)
    {
    	if(x == t) return low;
    	int temp = low , i , k;
    	for(i = head[x] ; i ; i = next[i])
    	{
    		if(val[i] && dis[to[i]] == dis[x] + 1)
    		{
    			k = dinic(to[i] , min(temp , val[i]));
    			if(!k) dis[to[i]] = 0;
    			val[i] -= k , val[i ^ 1] += k;
    			if(!(temp -= k)) break;
    		}
    	}
    	return low - temp;
    }
    bool judge(int mid)
    {
    	int i , sum = 0;
    	memset(head , 0 , sizeof(head)) , cnt = 1;
    	for(i = 1 ; i <= m ; i ++ ) add(s , i , 1) , add(i , x[i] + m , 1) , add(i , y[i] + m , 1);
    	for(i = 1 ; i <= n ; i ++ ) add(i + m , t , mid);
    	while(bfs()) sum += dinic(s , 1 << 30);
    	return sum == m;
    }
    int main()
    {
    	int i , l , r , mid , ans = 0;
    	scanf("%d%d" , &n , &m) , s = 0 , t = m + n + 1;
    	for(i = 1 ; i <= m ; i ++ ) scanf("%d%d" , &x[i] , &y[i]);
    	l = 0 , r = m;
    	while(l <= r)
    	{
    		mid = (l + r) >> 1;
    		if(judge(mid)) ans = mid , r = mid - 1;
    		else l = mid + 1;
    	}
    	printf("%d
    " , ans);
    	return 0;
    }
    

     

  • 相关阅读:
    30、Java中Set集合之HashSet、TreeSet和EnumSet
    此地址使用了一个通常用于网络浏览以外的端口。出于安全原因,Firefox 取消了该请求。
    C# 关闭显示器(显示)
    29、java中阻塞队列
    28、队列和栈
    27、ArrayList和LinkedList的区别
    26、线性表(List)
    WMI使用的WIN32_类库名
    android 怎样加速./mk snod打包
    hdu1081 最大子矩阵
  • 原文地址:https://www.cnblogs.com/GXZlegend/p/7115550.html
Copyright © 2011-2022 走看看