您的位置:首页 > 理论基础 > 计算机网络

POJ 2699 The Maximum Number of Strong Kings (网络流)

2016-01-22 19:04 357 查看
DescriptionA tournament can be represented by a complete graph in which each vertex denotes a player and a directed edge is from vertex x to vertex y if player x beats player y. For a player x in a tournamentT, the score of x is the number of players beaten by x. The score sequence of T, denoted by S(T) = (s1, s2, . . . , sn), is a non-decreasing list of the scores of all the players in T. It can be proved that S(T) = (s1, s2, . . . , sn) is a score sequence ofT if and only iffor k = 1, 2, . . . , n and equality holds when k = n. A player x in a tournament is a strong king if and only if x beats all of the players whose scores are greater than the score of x. For a score sequence S, we say that a tournament T realizes S if S(T)= S. In particular, T is a heavy tournament realizing S if T has the maximum number of strong kings among all tournaments realizing S. For example, see T2 in Figure 1. Player a is a strong king since the score of player a is the largest score in the tournament.Player b is also a strong king since player b beats player a who is the only player having a score larger than player b. However, players c, d and e are not strong kings since they do not beat all of the players having larger scores.The purpose of this problem is to find the maximum number of strong kings in a heavy tournament after a score sequence is given. For example,Figure 1 depicts two possible tournaments on five players with the same score sequence (1, 2, 2, 2, 3). We can see thatthere are at most two strong kings in any tournament with the score sequence (1, 2, 2, 2, 3) since the player with score 3 can be beaten by only one other player. We can also see that T2 contains two strong kings a and b. Thus, T2 is one of heavy tournaments.However, T1 is not a heavy tournament since there is only one strong king in T1. Therefore, the answer of this example is 2.InputThe first line of the input file contains an integer m, m <= 10, which represents the number of test cases. The following m lines contain m score sequences in which each line contains a score sequence.Note that each score sequence contains at most ten scores.OutputThe maximum number of strong kings for each test case line by line.Sample Input
5
1 2 2 2 3
1 1 3 4 4 4 4
3 3 4 4 4 4 5 6 6 6
0 3 4 4 4 5 5 5 6
0 3 3 3 3 3
Sample Output
2
4
5
3
5
题意:一场联赛可以表示成一个完全图,点表示参赛选手,比赛次数就为n*(n-1)/2。一个选手的得分等于被他打败的选手总数。一个选手被称为“strong king”当且仅当他打败了所有比他分高的选手。分数最高的选手也是 strong king。现在给出某场联赛所有选手的得分序列,由低到高,问合理安排每场比赛的结果后最多能有几个 strong king。已知选手总数不超过 10 个。
input输入测试组数T
接下来T行每一行不多于10个数,升序排列,代表每一位选手得分,每一行后输出最多有多少strong king 。
分析:最多才10位选手,那么我们就可以暴力枚举答案了,我们用match[i][j]表示i和j之间有一场比赛,我们还需要对每个比赛进行编号,id[i][j]=x表示i和j的比赛的编号为x。
那么我们开始建图,点分为几类:源点,汇点,选手,比赛编号。源点向每个人连一条边,容量为此时每个人的得分,因为每两个人只需打一次,所以每个比赛编号向汇点连一条边,容量为1。对于此时枚举的strong king人数num,那么对于这num个人要想成为strong king,那么他们必须打败得分比他高的人。对于其中一个候选人,我们只需把这个人与得分比他高的那些人的比赛编号连一条边,容量为1,这样连代表这个人必须赢得这场比赛,这样把num个人处理完后,对于其他选手,因为其他选手两两比赛时谁赢谁输无所谓了,我们关心的num个人已经处理好了,所以对于一场比赛match[i][j],我们把i和j分别向id[i][j](此次比赛编号)连一条容量为1的边,代表i可以赢得match[i][j]这场比赛,j也可以。这样跑最大流,跑完如果最大流等于比赛总次数n*(n-1)/2,那么代表着num个人可以成为strong king。
#include<stdio.h>#include<string.h>#include<vector>#include<queue>#include<algorithm>#include<sstream>#define maxn 2000#define LL long long#define inf 0x7fffffff#define INF 1e18using 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));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 main(){int T;char sss[100];int a[20];int fg[20][20];int id[20][20];scanf("%d",&T);getchar();while(T--){gets(sss);stringstream ss(sss);int n=0,xx;while(ss>>xx) a[++n]=xx;///这个方法处理特殊输入比较方便,把每个选手得分存在a数组里面int ans=0;int cnt=0;for(int i=1;i<=n;i++)for(int j=i+1;j<=n;j++)id[i][j]=++cnt;s=0,t=cnt+n+1;for(int x=n;x>=1;x--){init();memset(fg,0,sizeof(fg));for(int i=1;i<=n;i++)add(s,i,a[i]);for(int i=1;i<=cnt;i++)add(i+n,t,1);for(int i=n-x+1;i<=n;i++)///到这找答案,找到就break,跑完还没找到答案就是0{for(int j=i+1;j<=n;j++){if(a[i]<a[j]){fg[i][j]=1;///标记这场比赛已被控制add(i,id[i][j]+n,1);///必须赢得这场比赛}}}for(int i=1;i<=n;i++){for(int j=i+1;j<=n;j++){if(!fg[i][j])///其他比赛谁赢谁输无所谓了{add(i,id[i][j]+n,1);add(j,id[i][j]+n,1);}}}int tem=maxflow();if(tem==n*(n-1)/2){ans=x;break;}}printf("%d\n",ans);}return 0;}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: