现在的位置: 首页 > 综合 > 正文

sgu326告诉已赢的场数,还剩的场数,某人是否可能得冠军

2013年12月07日 ⁄ 综合 ⁄ 共 2104字 ⁄ 字号 评论关闭

       题意:现一个队有N个人,每个人已经赢了ai场,还有bi场比赛没打(可能不是跟本队的打,且比赛没有平局)。现给出N*N的矩阵g,g[i][j]表示i和j还有几场比赛要打(g[i][i]=0且g[i][j]=g[j][i])。问第一个人是否可能是整个队赢的最多的。

       分析:要第一个人赢的场数最多,那么第一个人剩下的场全部赢(也就确定了其它人最多赢的场数了),而其它人跟队外的人打的话一定要输。而对于g[i][j]来说,这么多场次肯定要人赢和输,我们考虑赢的情况。S连除第一个人,权值为第一个人赢的场数-已赢的场数,对于g[i][j]来说,i,j分别连场次,权值为g[i][j];场次连T,权值为g[i][j]。求最大流,判断是否为总的场次。如果是,那么就可能,输出YES。

#include<stdio.h>
#include<iostream>
using namespace std;

const int maxn=440;
const int maxm=21000;
const int maxint=0x3fffffff;
struct edge
{
	int u,v,w,next;
}e[maxm];

int S,T,n,a[maxn],b[maxn],pre[maxn],dist[maxn],g[maxn][maxn],edgeNum,first[maxn];
void Addedge(int u,int v,int w)
{
	e[edgeNum].u=u,e[edgeNum].v=v,e[edgeNum].w=w,e[edgeNum].next=first[u],first[u]=edgeNum++;
	e[edgeNum].u=v,e[edgeNum].v=u,e[edgeNum].w=0,e[edgeNum].next=first[v],first[v]=edgeNum++;
}

bool Dinic_Label()
{
	int i,j,k,head=0,tail=0,q[maxn];
    memset(pre,-1,sizeof(pre));
    memset(dist,0,sizeof(dist));
	q[tail++]=S;
	dist[S]=1;

	while(head!=tail)
	{
		k=q[head];
		head=(head+1)%maxn;
		for(i=first[k];i!=-1;i=e[i].next)
		{
			j=e[i].v;
			if(e[i].w>0&&!dist[j])//注意这里有e[i].w>0
			{
				dist[j]=dist[k]+1;
				if(j==T) return true;
				q[tail]=j;
				tail=(tail+1)%maxn;
			}
		}
	}
	return false;
}
int Dinic_Augment(int s)
{
	int i,j,min,sum;
	if(s==T)
	{
		for(min=maxint,i=pre[T];i!=-1;i=pre[e[i].u])//注意i=pre[e[i].u]而不是i=pre[i]
			if(min>e[i].w)
				min=e[i].w;

		for(i=pre[T];i!=-1;i=pre[e[i].u])//
		{
			e[i].w-=min;
			e[i^1].w+=min;//是^,而不是+1,-1
		}
		return min;
	}

	for(sum=0,i=first[s];i!=-1;i=e[i].next)
	{
		j=e[i].v;
		if(e[i].w>0&&dist[s]+1==dist[j])//e[i].w>0和dist[s]+1==dist[j]缺一不可
		{
			pre[j]=i;
		    sum+=Dinic_Augment(j);
		}
	}
	return sum;
}
int Dinic()
{
	int sum=0;

	while(Dinic_Label())
		sum+=Dinic_Augment(S);
	return sum;
}
int main()
{
	int i,j,k,sum,sum1;
	while(scanf("%d",&n)!=EOF)
	{
		for(i=0;i<n;i++)
			scanf("%d",&a[i]);
		for(i=0;i<n;i++)
			scanf("%d",&b[i]);
		k=a[0]+b[0];
		S=0,T=430;
		edgeNum=0;
		memset(first,-1,sizeof(first));
		for(sum=0,sum1=0,i=0;i<n;i++)
			for(j=0;j<n;j++)
			{
				scanf("%d",&g[i][j]);
				if(i&&i<j&&g[i][j])
				{
					Addedge(i,sum+n,g[i][j]);
					Addedge(j,sum+n,g[i][j]);
					Addedge(sum+n,T,g[i][j]);
					sum++;
					sum1+=g[i][j];
				}
			}
		for(i=1;i<n;i++)
		{
			if(k<a[i])
			{
				printf("NO\n");
				break;
			}
			else
				Addedge(S,i,k-a[i]);
		}
		if(i<n) continue;
		if(Dinic()==sum1) printf("YES\n");
		else printf("NO\n");
	}
	return 0;
}

 

抱歉!评论已关闭.