1757: Dicing

题目描述

 

Dicing is a two-player game and its outcome is fully random. Lately its popularity increases all over Byteotia. There is even a special club for dicing amateurs in the capital city of Byteotia. The club patrons take their time talking to each other and playing their favourite game with a randomly chosen opponent every once in a while. Everyone who wins the most games one day gains the title of the lucky chap. Sometimes it happens that the night at the club is a quiet one and only few games are played. It is a time when even one win can make you a lucky chap.

Once upon a time a most unlucky fellow, Byteasar, won the glorious title. He was so deeply shocked that he completely forgot how many games he had won. Now he is wondering how good his luck was and whether fortune finally smiled upon him - perhaps his luck changed for good? He knows exactly how many games and between whom were played that lucky night. However, he does not know the results. Byteasar desires to find out what is the smallest number of wins that could provide the title of the lucky chap. Be a good fellow and help him satisfy his curiosity!

Task

Write a programme that:

for each game played reads from the standard input the pair of players who competed in it.

finds the smallest number k, such that a set of games' outcomes exists in which each player wins k games at the most,writes the number k and the results of games in the found set to the standard output.

 

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

 

 

 

输入

 

 In the first line of the standard input there is a pair of integers n and m separated by a single space, 1 <= n <= 10 000, 0 <= m <= 10 000; n denotes the number of players, while m is the number of games. The players are numbered from 1 to n.

In the following m lines there are pairs of players' numbers depicting the sequence of games, separated by single spaces. One pair may occur many times in the sequence.

第1行:两个整数n和m,表示n个人参加游戏,每个人的编号为1至 n ,共进行了m场比赛

第2...m+1行: 两个整数a[i] 和b[i] ,表示第i场比赛的选手编号(同一组对手的比赛可能出现多次)

 

 

输出

 

 The first line of the standard output should contain the determined number k.

//For each pair of players' numbers a, b specified in the ith line of the input, in the ith line of the output the number 1 should be written if the player no. a wins against player no. b in the found set of outcomes, or 0 otherwise.

 

 

样例输入

<span style="color:#333333"><span style="color:#333333">4 4
1 2
1 3
1 4
1 2</span></span>

样例输出

<span style="color:#333333"><span style="color:#333333">1
</span></span>

提示

 

 

 

 

来源

poi2005

题解:

对于这题的单调性是显然的,所以我们可以二分答案,但是判断却是一个难题。

所以我们考虑网络流,建立m个虚点,表示每一场比赛,而每一个点有连向比赛的双方。

最后每一个人以mid为流量的边连向终点。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<deque>
#include<cstring>
#define INF 1e9
using namespace std;
int n,m,a[10005],b[10005],l,r,V[1000005],nex[1000005],las[250005],tot,W[1000005];
int s,t,de[250005],cur[250005];
void add(int t1,int t2,int t3)
{
    V[++tot]=t2;nex[tot]=las[t1];las[t1]=tot;W[tot]=t3;
    V[++tot]=t1;nex[tot]=las[t2];las[t2]=tot;W[tot]=0;
}
bool bfs()
{
    bool flag=0;
    deque<int>que;
    que.clear();
    memset(de,0,sizeof(de));
    de[s]=1;que.push_back(s);
    while(!que.empty())
    {
        int x=que.front();que.pop_front();
        if(x==t)flag=1;
        int h=las[x];
        while(h)
        {
            if(W[h]>0&&!de[V[h]])
                de[V[h]]=de[x]+1,que.push_back(V[h]);
            h=nex[h];
        }
    }
    return flag;
}
int dfs(int x,int p)
{
    if(x==t||!p)return p;
    int flow=0,fl;
    for(int i=cur[x];i;i=nex[i])
    {
        cur[x]=i;
        if(de[x]+1==de[V[i]])
        {
            fl=dfs(V[i],min(p-flow,W[i]));
            flow+=fl;W[i^1]+=fl;W[i]-=fl;
            if(flow==p)return flow;
        }
    }
    return flow;
}
bool pd(int mid)
{
    memset(las,0,sizeof(las));tot=1;
    s=m+n+1;t=m+n+2;
    /*for(int i=1;i<=n;++i)add(s,i,mid);
    for(int i=1;i<=m;++i)add(a[i],b[i]+n,1),add(b[i],a[i]+n,1);
    for(int i=n+1;i<=2*n;++i)add(i,t,INF);*/
    for(int i=1;i<=m;++i)add(s,n+i,1);
    for(int i=1;i<=m;++i)add(i+n,a[i],1),add(i+n,b[i],1);
    for(int i=1;i<=n;++i)add(i,t,mid);
    int sum=0;
    while(bfs())
    {
        for(int i=1;i<=t;++i)cur[i]=las[i];
        sum+=dfs(s,1e9);
    }
    return sum==m;
}
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;++i)scanf("%d%d",&a[i],&b[i]);
    r=m;
    while(l<r)
    {
        int mid=l+r>>1;
        if(pd(mid))r=mid;
        else l=mid+1;
    }
    cout<<l;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值