您的位置:首页 > 其它

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

2017-04-18 22:46 585 查看
The Maximum Number of Strong Kings

Time Limit: 1000MSMemory Limit: 65536K
Total Submissions: 2250Accepted: 1028
Description

A 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 tournament T, 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 of T if and only if


for 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 that
there 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.



Input

The 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.
Output

The 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

Source

Taiwan 2004
题目大意:

有N(N<=10)个人之间每两人之间进行一场比赛,每人得分是胜利数,若一个人赢了所有分数比他高的人,则他就是Strong King,给出每个人的分数,问最多有多少个Strong King。

解题思路:

对于这种答案取值范围非常小的题目我们可以尝试枚举答案,然后进行判断,这样就简化了许多。

首先枚举Strong King的数目。可以知道Strong King一定是分数最高的几个人,所以我们也就知道了哪几个人是Strong King。然后我们可以建一张图。设置一个原点一个汇点。第i个人拆成两个点i:表示这个人的胜场,i+N表示这个人的负场,从原点到i连一条容量为i所得分数的边,表示胜利数,从i+N到汇点连一条容量为N-1-i的得分的边表示失败数。然后把任意一个人的胜场和其他所有人的负场分别连接一条容量为1的边,表示他们之间可能的胜负关系。

然后对于我们每次枚举,由于Strong King必须赢分数比他高的人,所以我们就可以把原图中一些表示不确定关系的边去掉。若i必须赢j,就去掉i与j+N,j与i+N之间的边,并原点到i容量-1,j+N到汇点容量-1,这就相当于把之前i与j之间的不确定关系确定下来。当然胜负场数不能是负数,所以如果与源点汇点邻接的边容量变为负数则停止枚举。建好图后,我们需要判断这样能不能使得其他场次能够正常进行比赛。这时跑一边最大流。如果从源点发出的边全部满流,则说明其他比赛能正常进行。当前情况正确,否则说明有比赛无法进行下去,当前情况错误。

AC代码:

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <queue>
#include <vector>
#include <sstream>
using namespace std;
#define mem(a,b) memset((a),(b),sizeof(a))
#define INF 0x3f3f3f3f

const int MAXN=10+3;
const int MAXV=MAXN*2;

struct Edge
{
int to,cap,rev;
Edge(int t,int c,int r):to(t),cap(c),rev(r){}
};

int score[MAXN],N;
string s;
vector<Edge> G[MAXV];
int level[MAXV];
int iter[MAXV];

void bfs(int s)
{
mem(level,-1);
queue<int> que;
level[s]=0;
que.push(s);
while(!que.empty())
{
int v=que.front(); que.pop();
for(int i=0;i<G[v].size();++i)
{
Edge &e=G[v][i];
if(e.cap>0&&level[e.to]<0)
{
level[e.to]=level[v]+1;
que.push(e.to);
}
}
}
}

int dfs(int v,int t,int f)
{
if(v==t)
return f;
for(int &i=iter[v];i<G[v].size();++i)
{
Edge &e=G[v][i];
if(e.cap>0&&level[v]<level[e.to])
{
int d=dfs(e.to,t,min(f,e.cap));
if(d>0)
{
e.cap-=d;
G[e.to][e.rev].cap+=d;
return d;
}
}
}
return 0;
}

int dinic(int s,int t)
{
int flow=0;
for(;;)
{
bfs(s);
if(level[t]<0)
return flow;
mem(iter,0);
int f;
while((f=dfs(s,t,INF))>0)
flow+=f;
}
}

void add_edge(int from,int to,int cap)
{
G[from].push_back(Edge(to,cap,(int)G[to].size()));
G[to].push_back(Edge(from,0,(int)G[from].size()-1));
}

void init()
{
for(int i=0;i<MAXV;++i)
G[i].clear();
}

int main()
{
int T;
getline(cin,s);
istringstream is(s);
is>>T;
while(T--)
{
getline(cin,s);
istringstream is(s);
int tmp;
N=0;
while(is>>tmp)
score[N++]=tmp;
int the_min=1;//分数最高的几个人一定都是Strong King
for(int i=N-2;i>=0;--i)//统计分数最高的人的数目
if(score[i]==score[i+1])
++the_min;
else break;
int ans=N;
while(ans>the_min)//枚举答案
{
init();
//0~N-1  胜利点
//N~2*N 负点
//N*2   源点
//N*2+1 汇点
int s=N*2,t=N*2+1,cost[MAXN]={0},cost_l[MAXN]={0};
bool added[MAXN][MAXN]={0},ok=true;
for(int i=0;i<ans;++i)//枚举每个Strong King
{
int u=N-1-i;
for(int v=u+1;v<N;++v)
if(score[v]>score[u])//必须赢分数比他高的人
{
++cost_l[u];
++cost[v];
if(cost[v]>N-1-score[v])//分数比他高的人不会输这么多次
{
ok=false;
break;
}
added[u][v]=true;
}
}
for(int i=0;i<N;++i)
{
add_edge(s, i, score[i]-cost_l[i]);
add_edge(i+N, t, N-1-score[i]-cost[i]);
for(int j=0;j<N;++j)
if(i!=j&&!added[i][j]&&!added[j][i])//i与j之间进行比赛
add_edge(i, j+N, 1);
}
dinic(s, t);
for(int i=0;i<G[s].size();++i)
{
if(G[s][i].cap!=0)//无法完成全部比赛
{
ok=false;
break;
}
}
if(ok)
break;

--ans;
}
printf("%d\n",ans);
}

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: