sgu326告訴已贏的場數,還剩的場數,某人是否可能得冠軍

       題意:現一個隊有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;
}


 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章