• [Luogu3425][POI2005]KOS-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!
    TaskWrite a programme that:
    for each game played reads from the standard input the pair of players who competed in it.
    finds the smallest number kkk, such that a set of games' outcomes exists in which each player wins kkk games at the most,writes the number kkk 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 nnn and mmm separated by a single space, 1≤n≤100001le nle 100001≤n≤10000, 0≤m≤100000le mle 100000≤m≤10000; nnn denotes the number of players, while mmm is the number of games. The players are numbered from 111 to nnn. In the following mmm 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.
    输出格式:
    The first line of the standard output should contain the determined number kkk. For each pair of players' numbers aaa, bbb specified in the iii'th line of the input, in the iii'th line of the output the number 111 should be written if the player no. aaa wins against player no. bbb in the found set of outcomes, or 000 otherwise.
    输入输出样例
    输入样例#1
    4 4
    1 2
    1 3
    1 4
    1 2
    输出样例#1
    1
    0
    0
    0
    1

    题解

    给每个人,每场比赛都新建一个点
    源点流向每个人,容量二分
    每个人连向他参加的每一场比赛,容量为1
    每场比赛流向汇点,容量为1
    二分每次check最大流是否等于总比赛场数m
    记得二分得到答案后还要在check一次答案用于输出方案

    code

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<queue>
    using namespace std;
    #define inf 1000000000
    const int N = 10010;
    struct edge{int to,next,w;}a[N<<4];
    int n,m,s,t,l,r,A[N],B[N],head[N<<1],cnt,dep[N<<1],cur[N<<1],ans;
    queue<int>Q;
    void link(int u,int v,int w)
    {
    	a[++cnt]=(edge){v,head[u],w};
    	head[u]=cnt;
    	a[++cnt]=(edge){u,head[v],0};
    	head[v]=cnt;
    }
    bool bfs()
    {
    	memset(dep,0,sizeof(dep));
    	dep[s]=1;Q.push(s);
    	while (!Q.empty())
    	{
    		int u=Q.front();Q.pop();
    		for (int e=head[u];e;e=a[e].next)
    			if (!dep[a[e].to]&&a[e].w)
    				dep[a[e].to]=dep[u]+1,Q.push(a[e].to);
    	}
    	return dep[t];
    }
    int dfs(int u,int flow)
    {
    	if (u==t)
    		return flow;
    	for (int &e=cur[u];e;e=a[e].next)
    		if (dep[a[e].to]==dep[u]+1&&a[e].w)
    		{
    			int temp=dfs(a[e].to,min(a[e].w,flow));
    			if (temp) {a[e].w-=temp;a[e^1].w+=temp;return temp;}
    		}
    	return 0;
    }
    bool check(int mid)
    {
    	memset(head,0,sizeof(head));cnt=1;
    	for (int i=1;i<=n;i++)
    		link(s,i,mid);
    	for (int i=1;i<=m;i++)
    		link(A[i],i+n,1),link(B[i],i+n,1),link(i+n,t,1);
    	ans=0;
    	while (bfs())
    	{
    		for (int i=t;i;i--) cur[i]=head[i];
    		while (int temp=dfs(s,inf)) ans+=temp;
    	}
    	return ans==m;
    }
    int main()
    {
    	scanf("%d%d",&n,&m);s=n+m+1;t=s+1;
    	for (int i=1;i<=m;i++)
    		scanf("%d%d",&A[i],&B[i]);
    	l=0;r=m;
    	while (l<r)
    	{
    		int mid=l+r>>1;
    		if (check(mid)) r=mid;
    		else l=mid+1;
    	}
    	printf("%d
    ",l);check(l);
    	for (int i=1;i<=m;i++)
    		for (int e=head[i+n];e;e=a[e].next)
    			if (a[e].w) puts(a[e].to==A[i]?"1":"0");
    	return 0;
    }
    
  • 相关阅读:
    Tree的两种存储形式
    滚轮缩放效果
    从hello world 说程序运行机制
    词法分析器的实现
    MSDN中回调函数的讲解及其C#例子:用委托实现回调函数
    在后台new出页面(组件)
    HTML中多种空格转义字符
    ios 博客集合
    IOS学习
    Apple Swift编程语言入门教程
  • 原文地址:https://www.cnblogs.com/zhoushuyu/p/8146219.html
Copyright © 2020-2023  润新知