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.

 

 

样例输入

4 4
1 2
1 3
1 4
1 2

样例输出

1

提示

 

 

 

 

来源

poi2005

题解:

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

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

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

#include
#include
#include
#include
#include
#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;
    dequeque;
    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>1;
        if(pd(mid))r=mid;
        else l=mid+1;
    }
    cout<

 

你可能感兴趣的:(1757: Dicing)