326. Perspective
Time limit per test: 0.5 second(s)
Memory limit: 65536 kilobytes
input: standard
output: standard
Breaking news! A Russian billionaire has bought a yet undisclosed NBA team. He's planning to invest huge effort and money into making that team the best. And in fact he's been very specific about the expected result: the first place.
Being his advisor, you need to determine whether it's possible for your team to finish first in its division or not.
More formally, the NBA regular season is organized as follows: all teams play some games, in each game one team wins and one team loses. Teams are grouped into divisions, some games are between the teams in the same division, and some are between the teams in different divisions.
Given the current score and the total number of remaining games for each team of your division, and the number of remaining games between each pair of teams in your division, determine if it's possible for your team to score at least as much wins as any other team in your division.
Input
The first line of input contains
N (2 ≤
N ≤ 20) — the number of teams in your division. They are numbered from 1 to
N, your team has number 1.
The second line of input contains
N integers
w
1,
w
2,...,
w
N, where
w
i is the total number of games that
i
th team has won to the moment.
The third line of input contains
N integers
r
1,
r
2,...,
r
N, where
r
i is the total number of remaining games for the
i
th team (including the games inside the division).
The next
N lines contain
N integers each. The
j
th integer in the
i
th line of those contains
a
ij — the number of games remaining between teams
i and
j. It is always true that
a
ij=a
ji and
a
ii=0, for all
i a
i1 +
a
i2 +... +
a
iN ≤
r
i.
All the numbers in input are non-negative and don't exceed 10\,000.
Output
On the only line of output, print "
YES
" (without quotes) if it's possible for the team 1 to score at least as much wins as any other team of its division, and "
NO
" (without quotes) otherwise.
Example(s)
sample input |
sample output |
3
1 2 2
1 1 1
0 0 0
0 0 0
0 0 0
|
YES
|
sample input |
sample output |
3
1 2 2
1 1 1
0 0 0
0 0 1
0 1 0
|
NO
|
/*
题意描述:一个赛区有n支球队,给出这n支球队目前已经赢的场数,
和剩下还要打的场数(该场数包含赛区内与不是本赛区内的),
问球队1有没有可能取得本赛区成绩第一允许并列,每场比赛没有平局的情况
解法(参考网上思路):首先为了让该球对能够赢,那么该球队剩下的场数肯定都要赢,那么该赛区的其他对和别的赛区的比赛都必须输,和该赛区的1队打也必须输,这样就1队拿第一的概率才会增大!然后还有本赛区的两只(不包含1队)队伍打,那么这就使得其中一个队的分数会增加,所以该题主要解决的问题是如何分配比赛的胜负使得最大得分最小!
这里这样建图:建一个源点和汇点,两个对之间有比赛作为一个点称作为比赛点,首先是源点连接比赛点权值为该边的权值,比赛点连接与之关联的两个球队,后每个球队连接汇点,权值为对1的最高分减去当前该队的得分(如果说源点出发的边都是满流那么输出YES否则输出NO)
我们来理解一下这个建图方式:源点到每个比赛点的权值可以看成是总的要用来分配的分数(必须分配完),球队点到汇点的权值表示该球队最多还能分到的分数,如果用来分配的分数没有分配完那么则说明继续分将会使某个队的总得分超过球队1的得分,则说明不可能,若过已经分完那么则说明球队1有可能成为第一
这里注意一点:如果球队1可能的最高得分比某个球队的目前得分还低的话那么则直接输出NO
*/
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
using namespace std;
const int N=4002;
const int M=30002;
const int INF=1<<29;
int t,n,m,tot;
int gap[M],dis[M],pre[M],head[N],cur[N];
int NE,NV,sink,source,a[N][N],w[N],r[N];
struct Node
{
int c,pos,next;
} E[M*4];
#define FF(i,NV) for(int i=0;i<NV;i++)
int sap(int s,int t)
{
memset(dis,0,sizeof(int)*(NV+1));
memset(gap,0,sizeof(int)*(NV+1));
FF(i,NV) cur[i] = head[i];
int u = pre[s] = s,maxflow = 0,aug =INF;
gap[0] = NV;
while(dis[s] < NV)
{
loop:
for(int &i = cur[u]; i != -1; i = E[i].next)
{
int v = E[i].pos;
if(E[i].c && dis[u] == dis[v] + 1)
{
aug=min(aug,E[i].c);
pre[v] = u;
u = v;
if(v == t)
{
maxflow += aug;
for(u = pre[u]; v != s; v = u,u = pre[u])
{
E[cur[u]].c -= aug;
E[cur[u]^1].c += aug;
}
aug =INF;
}
goto loop;
}
}
if( (--gap[dis[u]]) == 0) break;
int mindis = NV;
for(int i = head[u]; i != -1 ; i = E[i].next)
{
int v = E[i].pos;
if(E[i].c && mindis > dis[v])
{
cur[u] = i;
mindis = dis[v];
}
}
gap[ dis[u] = mindis+1 ] ++;
u = pre[u];
}
return maxflow;
}
void addEdge(int u,int v,int c )
{
E[NE].c = c;
E[NE].pos = v;
E[NE].next = head[u];
head[u] = NE++;
E[NE].c = 0;
E[NE].pos = u;
E[NE].next = head[v];
head[v] = NE++;
}
int main()
{
while(scanf("%d",&n)!=EOF)
{
NE=0;
//memset(head,-1,sizeof(head));
int i,j,sum=0;
for(i=1;i<=n;i++)
{
scanf("%d",&w[i]);
}
for(i=1;i<=n;i++)
{
scanf("%d",&r[i]);
}
w[1]+=r[1];
int k=0;
for(i=1;i<=n;i++)
{
for(j=1;j<=n;j++)
{
scanf("%d",&a[i][j]);
if(i<j&&a[i][j]&&i>1)k++,sum+=a[i][j];
}
}
source=0,sink=k+n+1,NV=sink+1;
for(i=0;i<=NV;i++)head[i]=-1;
for(k=1,i=2;i<=n;i++)
{
for(j=i+1;j<=n;j++)
{
if(a[i][j])
{
addEdge(source,k+n,a[i][j]);
addEdge(k+n,i,INF);
addEdge(k+n,j,INF);
k++;
}
}
}
for(i=2;i<=n;i++)
{
if(w[1]>=w[i])
addEdge(i,sink,w[1]-w[i]);
else break;
}
if(i>n&&sum==sap(source,sink))
{
printf("YES\n");
}else printf("NO\n");
}
return 0;
}
/*
3
1 2 2
1 1 1
0 0 0
0 0 0
0 0 0
3
1 2 2
1 1 1
0 0 0
0 0 1
0 1 0
*/