SGU 326 Perspective (网络流)

Description



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 ia 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.

Sample Input

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


题意:NBA 某小组内有 N 支球队,小组内以及小组间已经进行了若干场比赛。现在给出这 N 支球队目前胜利的场数、还剩多少场没有比(包括小组内和小组间)以及小组内任意两支球队之间还剩多少场没有比,存在maze[i][j]中, 问能否合理安排剩下的所有比赛,使得球队 1 最后胜利的场数至少和小组内任何一支其他球队一样。 (2 <= N <= 20,0 <= x <= 10000, x 表示其他任何输入)

分析:首先,所有和球队1相关的比赛都让1赢,胜场记为win=w[1]+r[1](已经赢得加上还剩下的比赛),如果已经此时仍然有球队胜利的场数大于球队1,那不管怎么挣扎,就算让这个球队剩下的比赛全输,球队1都不可能赢了对吧。除了1的其他球队所有组间赛都让他输(组间赛的场数可求,因为告诉了r[i]和组内的剩下比赛),组内赛再说。既然约定与球队1相关的比赛都是1赢,那么剩下的比赛中与1相关的比赛就不用管了,都已经是1赢了,调整不了了,因为每个球队已经有过胜场,那么要使球队1拿第一,那么其他球队i在剩下的比赛赢场最多为win-w[i]。

现在可以开始建图了,我们把点分为几类:源点,汇点,球队(除球队1),比赛(除开和1有关的比赛)。 首先,源点向每个球队连一条边,容量为该球队最多胜场(win-w[i]),因为每个球队接下来还要打比赛,所以对于某次比赛maze[i][j](其中i!=1,j!=1),我们让i和j分别与此次比赛连边,容量都为inf,或者maze[i][j],再把此次比赛与汇点连一条边,容量为maze[i][j],每场比赛都用一个特定的数值代替就可以建图了。最后,sum记录和球队1无关的所有组内赛总数(因为我们建图全是组内赛,组间赛已经让他们输了,没必要考虑),看看跑出的最大流是否等于sum,如果等于那么可以调整让球队1 赢,因为其他球队的剩下的比赛不管输赢都正常进行了。

#include<stdio.h>
#include<string.h>
#include<vector>
#include<queue>
#include<algorithm>
#define maxn 2000
#define inf 0x7fffffff
using namespace std;
struct edge
{
    int from,to,cap,flow;
};
vector<edge> edges;
vector<int> G[maxn];
int d[maxn],cur[maxn];
bool vis[maxn];
int s,t;
void init()
{
    for(int i=0;i<maxn;i++) G[i].clear();
    edges.clear();
}
void add(int from,int to,int cap)
{
    edges.push_back((edge){from,to,cap,0});
    edges.push_back((edge){to,from,0,0});
    int m=edges.size();
    G[from].push_back(m-2);
    G[to].push_back(m-1);
}
bool bfs()
{
    memset(vis,false,sizeof(vis));
    memset(d,0,sizeof(d));
    queue<int> q;
    q.push(s);
    d[s]=0,vis[s]=true;
    while(!q.empty())
    {
        int x=q.front();
        q.pop();
        for(int i=0;i<G[x].size();i++)
        {
            edge& e=edges[G[x][i]];
            if(!vis[e.to]&&e.cap>e.flow)
            {
                vis[e.to]=true;
                d[e.to]=d[x]+1;
                q.push(e.to);
            }
        }
    }
    return vis[t];
}
int dfs(int x,int a)
{
    if(x==t||a==0) return a;
    int flow=0,f;
    for(int& i=cur[x];i<G[x].size();i++)
    {
        edge& e=edges[G[x][i]];
        if(d[x]+1==d[e.to]&&(f=dfs(e.to,min(a,e.cap-e.flow)))>0)
        {
            e.flow+=f;
            edges[G[x][i]^1].flow-=f;
            flow+=f;
            a-=f;
            if(a==0) break;
        }
    }
    return flow;
}
int maxflow()
{
    int flow=0;
    while(bfs())
    {
        memset(cur,0,sizeof(cur));
        flow+=dfs(s,inf);
    }
    return flow;
}
int w[30],r[30],maze[30][30];
int main()
{
    int n;
    while(scanf("%d",&n)==1)
    {
        s=0,t=1000;
        for(int i=1;i<=n;i++) scanf("%d",&w[i]);
        for(int i=1;i<=n;i++) scanf("%d",&r[i]);
        int win=w[1]+r[1],sum=0,flog=1;
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++)
            scanf("%d",&maze[i][j]);
        init();
        for(int i=2;i<=n;i++)
        {
            if(win-w[i]<0)///如果某支球队已经赢得场数都大于球队1最大可能赢得场数,那么GG,怎么也不可能赢了
            {
                flog=0;
                break;
            }
            add(s,i+400,win-w[i]);
        }
        if(flog==0)
        {
            puts("NO");
            continue;
        }
        for(int i=2;i<=n;i++)
        {
            for(int j=i+1;j<=n;j++)
            {
                if(maze[i][j]<=0) continue;
                sum+=maze[i][j];///比赛场数
                add((i-1)*n+j,t,maze[i][j]);///比赛与汇点连边
                add(i+400,(i-1)*n+j,maze[i][j]);///球队与比赛连边
                add(j+400,(i-1)*n+j,maze[i][j]);///球队与比赛连边
            }
        }
        int ans=maxflow();
        if(sum==ans) puts("YES");
        else puts("NO");
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值