1. 程式人生 > >【WHUOJ124】Football Coach

【WHUOJ124】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;
}