【WHUOJ124】Football Coach

124. Football Coach

Description

It is not an easy job to be a coach of a football team. The season is almost over, only a few matches are left to play. All of sudden the team
manager comes to you and tells you bad news: the main sponsor of your club is not happy with your results and decided to stop sponsoring your
team, which probably means the end of your club. The sponsor's decision is final and there is no way to change it unless... unless your team
miraculously wins the league.
The manager left you in deep thought. If you increase the number of practices and offer players a generous bonus for each match, you may be
able to win all the remaining matches. Is that enough? You also have to make sure that teams with many points lose against teams with few
points so that in the end, your team will have more points than any other team. You know some of the referees and can bribe them to manipulate
the result of each match. But first you need to figure out how to manipulate the results and whether it is possible at all.
There are N teams numbered 1 through N, your team has the number N. The current number of points of each team and the list of remaining
matches are given. Your task is to find out whether it is possible to manipulate each remaining match so that the team N will finish with
strictly more points than any other team. If it is possible, output "YES", otherwise, output "NO". In every match, the winning team gets 2
points, the losing team gets 0. If the match ends with a draw, both teams get 1 point.

Input

There will be multiple test cases. Each test case has the following form: The first line contains two numbers N(1 <= N <= 100) and M(0 <= M <=
1000). The next line contains N numbers separated by spaces giving the current number of points of teams 1, 2, ..., N respectively. The
following M lines describe the remaining matches. Each line corresponds to one match and contains two numbers a and b (a not equal to b, 1 <=
a,b <= N) identifying the teams that will play in the given match. There is a blank line after each test case.

Output

For each test case, output "YES" or "NO" to denote whether it's possible to manipulate the remaining matches so that the team N would win
the league.

Sample Input

5 8
2 1 0 0 1
1 2
3 4
2 3
4 5
3 1
2 4
1 4
3 5
5 4
4 4 1 0 3
1 3
2 3
3 4
4 5

Sample Output

YES
NO

Hint

The problem is so hard that even I have told you the method here is "maximum network flow", you can't solve it. You can have a try, but don?t waste too much time here if you are not perfect at modeling a network.

 

题意:
       有 n 支球队,互相之间已经进行了一些比赛,还剩下 m 场没有比。现在给出各支球队目前的总分以及还剩下哪 m 场没有比,问能否合理安排这 m 场比赛的结果,使得第 n 支球队最后的总分大于其他任何一支球队的总分。已知每场比赛胜者得 2 分,败者 0 分,平局则各得 1 分。

解析:

       最大流。

       构图是真的妙。。。

       首先跟 n 有关的比赛全部让 n 赢。 其他相当于是把两分分配给两个球队,变成一个匹配问题了。不超过 n 只用限制一下匹配上限,然后看一看能不能分配完就行了,具体看代码。

       注意特判如果第 n 队把能赢的都赢了还是有其他队出事分数大于等于他则无解,否则最大流就会有负边权。。。

       还有puts这东西会自动换行,再加换行符就GG。。。

 

代码:

#include <bits/stdc++.h>
using namespace std;

const int inf=1e9;
const int Max=1205;
const int Maxm=4005;
int n,m,size,ans,sum,s,t,tag;
int first[Max],num[Max],dep[Max],tmp[Max];
struct shu{int to,next,len;};
shu edge[Maxm<<1];

inline int get_int()
{
	int x=0,f=1;
	scanf("%d",&x);return x;
	char c;
	for(c=getchar();(!isdigit(c))&&(c!='-');c=getchar());
	if(c=='-') f=-1,c=getchar();
	for(;isdigit(c);c=getchar()) x=(x<<3)+(x<<1)+c-'0';
	return x*f;
}

inline void clean()
{
	size=1,sum=ans=tag=0;
	memset(first,0,sizeof(first));
}

inline void build(int x,int y,int z)
{
	edge[++size].next=first[x],first[x]=size,edge[size].to=y,edge[size].len=z;
	edge[++size].next=first[y],first[y]=size,edge[size].to=x,edge[size].len=0;
}

inline void pre()
{
	t=n+m+2;
	for(int i=1;i<=n;i++) num[i]=get_int();
	for(int i=1;i<=m;i++)
	{
	  int x=get_int(),y=get_int();
	  if(x!=n&&y!=n) build(s,i,2),build(i,m+x,2),build(i,m+y,2),sum+=2;
	  else num[n]+=2;
	}
	for(int i=1;i<n;i++)
	{
	  if(num[i]>=num[n]) {tag=1;return;}
	  build(i+m,t,num[n]-num[i]-1);
	}
}

inline bool bfs()
{
	memset(dep,0,sizeof(dep));
	queue<int>q;q.push(s),dep[s]=1;
	while(q.size())
	{
	  int p=q.front();q.pop();
	  for(int u=first[p];u;u=edge[u].next)
	  {
	  	int to=edge[u].to;
	  	if(!dep[to]&&edge[u].len)
	  	{
	  	  dep[to]=dep[p]+1,q.push(to);
	  	  if(to==t) return 1;
	  	}
	  }
	}
	return 0;
}

inline int dinic(int p,int flow)
{
	if(p==t) return flow;
	int sum=0;
	for(int &u=tmp[p];u&&sum<flow;u=edge[u].next)
	{
	  int to=edge[u].to;
	  if(edge[u].len&&dep[to]==dep[p]+1)
	  {
	    int minn=dinic(to,min(flow-sum,edge[u].len));
	    if(!(flow-sum)) {dep[to]=0;break;}
	    edge[u].len-=minn,edge[u^1].len+=minn,sum+=minn;
	  }
	}
	return sum;
}

inline void solve()
{
	while(bfs())
	{
	  memcpy(tmp,first,sizeof(tmp));
	  ans+=dinic(s,inf);
	}
	(ans==sum)?puts("YES"):puts("NO");
}

int main()
{
	while(~scanf("%d%d",&n,&m))
	{
	  clean();
	  pre();
	  if(tag){puts("NO");continue;}
	  solve();
	}
	return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值