poj2699 The Maximum Number of Strong Kings

Posted MashiroSky

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了poj2699 The Maximum Number of Strong Kings相关的知识,希望对你有一定的参考价值。

http://poj.org/problem?id=2699 (题目链接)

题意

  给出1张有向完全图。U->V表示U可以打败V并得一分。如果一个人的得分最高,或者他打败所有比自己得分高的人,那么此人就是king。现在按顺序给出每个人的得分,求最多可能有多少个king同时存在。

Solution

  想了半天贪心,然而得分相等的情况真的很不好处理。。真的没想到是最大流。。左转题解:http://blog.csdn.net/sdj222555/article/details/7797257

  考虑这样建图的正确性。

  借用题解的example,假设序列长成这样:1....i......n。那么i不是king有以下这几种情况

  1.i的得分少于得分比它大的人的个数

  这种情况显然i不可能赢所有得分比它大的人,那么这如何在我们所构建的图上体现呢?

  对于i与得分比i大的人的比赛,从i连向它们,显然,这些边不可能满流,因为i不可能赢这么多场,于是不成立。

  2.n已经无法给予i赢的机会

  因为得分比i大的人想要成为King,必须赢得得分比他们更大的人n,而n能够输的场次是有限的。

  如果从i连向(i,n)的比赛使i强行赢得胜利,会使得边(s,n)不满流,于是不成立。

  也许还有别的情况我没考虑到,唉最近思维僵化,没救了,如果有补充请提出╮(╯_╰)╭

细节

  多组数据注意初始化,为什么我还是要16ms。。自带常数。。

代码

// poj2699
#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<queue>
#define LL long long
#define inf 2147483640
#define Pi acos(-1.0)
#define free(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout);
using namespace std;

const int maxn=1010;
struct edge {int to,next,w;}e[maxn];
int head[maxn],d[maxn],f[20][20],a[maxn],Max;
int n,m,ans,cnt=1,es,et;
char ch[maxn];

void link(int u,int v,int w) {
	e[++cnt]=(edge){v,head[u],w};head[u]=cnt;
	e[++cnt]=(edge){u,head[v],w};head[v]=cnt;
}
void read() {
	gets(ch);
	n=m=Max=0;int l=strlen(ch);
	for (int i=0;i<l;i++) if (ch[i]>=‘0‘ && ch[i]<=‘9‘) {
			m=m*10+ch[i]-‘0‘;
			if (i==l || ch[i+1]<‘0‘ || ch[i+1]>‘9‘) a[++n]=m,m=0,Max=max(Max,a[n]);
		}
	for (int i=1;i<=n;i++)
		for (int j=i+1;j<=n;j++) f[i][j]=f[j][i]=++m;
	es=n+m+1;et=es+1;
}
void Init() {
	cnt=ans=0;
	memset(head,0,sizeof(head));
}
bool bfs() {
	memset(d,-1,sizeof(d));
	queue<int> q;q.push(es);d[es]=0;
	while (!q.empty()) {
		int x=q.front();q.pop();
		for (int i=head[x];i;i=e[i].next) if (e[i].w && d[e[i].to]<0) {
				d[e[i].to]=d[x]+1;
				q.push(e[i].to);
			}
	}
	return d[et]>0;
}
int dfs(int x,int f) {
	if (x==et || f==0) return f;
	int used=0,w;
	for (int i=head[x];i;i=e[i].next) if (e[i].w && d[e[i].to]==d[x]+1) {
			w=dfs(e[i].to,min(e[i].w,f-used));
			used+=w;
			e[i].w-=w;e[i^1].w+=w;
			if (used==f) return used;
		}
	if (!used) d[x]=-1;
	return used;
}
void Dinic() {
	while (bfs()) ans+=dfs(es,inf);
}
int main() {
	int T;scanf("%d",&T);getchar();
	while (T--) {
		read();
		for (int s=1;s<=n;s++) {
			Init();
			for (int i=1;i<=n;i++) link(es,i,a[i]);
			for (int i=1;i<s;i++)
				for (int j=i+1;j<=n;j++) link(i,f[i][j]+n,1),link(j,f[i][j]+n,1);
			for (int i=s;i<=n;i++)
				for (int j=i+1;j<=n;j++) {
					link(i,f[i][j]+n,1);
					if (a[i]==Max) link(j,f[i][j]+n,1);
				}
			for (int i=n+1;i<=n+m;i++) link(i,et,1);
			Dinic();
			if (ans==m) {printf("%d\n",n-s+1);break;}
		}
	}
	return 0;
}

  

以上是关于poj2699 The Maximum Number of Strong Kings的主要内容,如果未能解决你的问题,请参考以下文章

POJ 2699 The Maximum Number of Strong Kings Description

poj2699 The Maximum Number of Strong Kings

POJ 2699 The Maximum Number of Strong Kings (最大流+枚举)

POJ2699The Maximum Number of Strong Kings(二分,最大流)

poj2699

poj2699 转化为可行性判定问题+二分枚举+最大流