标签:
Description


Input
Output
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
题目大意:有kase组数据。每组数据有一些人两两比赛,告诉你每个人赢得比赛的次数。如果一个人满足它打败了所有分数严格大于它的那个人,则它成为King;当然分数最高的人们自然也都是King。那么请问这场比赛最多能产生多少King呢?
分析:数据规模小的可怜,至多10组数据,每组数据至多10个人。首先明确一个贪心,就是King一定是比分最高的几个人,因为如果比分低的反而是King那么比分比它高的更容易成为King。然后注意的是不确定的输入我的处理办法是用stringstream提取一行即可。
然后我们用最大流的思路来解决。超级源点与所有选手相连,负载为胜利的次数。首先我们要去试探有几个King的时候满足条件,我采用的是二分,由于规模很小,枚举也行。然后在Kings确定了之后,对于每场比赛也看成一个节点,遍历两两选手i,j。如果i是King且score[j]>score[i],说明这场比赛i一定要赢,那么选手i与这场比赛连接,负载为1。如果不满足以上条件则说明此场胜负无所,选手i
、j 都与这场比赛连接,负载为1。最后再让每场比赛与超级汇点连接,负载为1。再跑最大流看看是否最大流=比赛总数n*(n-1)/2。根据结果二分。(枚举的话从低开始往高找,找到一组解即为最优解)。
上代码:
#include<iostream>
#include<cstring>
#include<algorithm>
#include<queue>
#include<cstdio>
#include<sstream>
#include<string>
using namespace std;
const int MAXN = 210;
const int MAXM = 41000;
const int INF = 0x3f3f3f3f;
struct Edge
{
int from, to, cap, next;
};
Edge edge[MAXM];
int level[MAXN];
int head[MAXN];
int score[MAXN];
int bigger[MAXN];
int src, des, cnt;
void addedge( int from, int to, int cap )
{
edge[cnt].from = from;
edge[cnt].to = to;
edge[cnt].cap = cap;
edge[cnt].next = head[from];
head[from] = cnt++;
swap( from, to );
edge[cnt].from = from;
edge[cnt].to = to;
edge[cnt].cap = cap;
edge[cnt].next = head[from];
head[from] = cnt++;
}
int bfs()
{
memset( level, -1, sizeof level );
queue<int> q;
while (!q.empty())
q.pop();
level[src] = 0;
q.push( src );
while (!q.empty())
{
int u = q.front();
q.pop();
for (int i = head[u]; i != -1; i = edge[i].next)
{
int v = edge[i].to;
if (edge[i].cap&&level[v] == -1)
{
level[v] = level[u] + 1;
q.push( v );
}
}
}
return level[des] != -1;
}
int dfs( int u, int f )
{
if (u == des) return f;
int tem;
for (int i = head[u]; i != -1; i = edge[i].next)
{
int v = edge[i].to;
if (edge[i].cap&&level[v] == level[u] + 1)
{
tem = dfs( v, min( f, edge[i].cap ) );
if (tem > 0)
{
edge[i].cap -= tem;
edge[i ^ 1].cap += tem;
return tem;
}
}
}
level[u] = -1;
return 0;
}
int Dinic()
{
int ans = 0, tem;
while (bfs())
{
while (tem = dfs( src, INF ))
{
ans += tem;
}
}
return ans;
}
int main()
{
int kase;
cin >> kase;
getchar();
src = 0; des = 105;
while (kase--)
{
int n = 0;
string str;
getline( cin, str );
stringstream ss( str );
int sc;
while (ss >> sc)
{
score[++n] = sc;
}
bigger[n] = 0;
for (int i = n - 1; i >= 1; i--)
{
if (score[i] == score[i + 1]) bigger[i] = bigger[i + 1];
else bigger[i] = n - i;
}
int start;
for ( start = 1; start <= n; start++)
{
if (score[start] >= bigger[start])break;
}
int low = start, high = n;
int ans = start;
while(low<=high)
{
int mid = (low + high) / 2;
memset( head, -1, sizeof head );
cnt = 0;
int match = 0;
for (int i = 1; i <= n; i++)
{
addedge( src, i, score[i] );
}
for (int i = 1; i <= n; i++)
{
for (int j = i+1; j <= n; j++)
{
if (i >= mid&&score[j] > score[i])
addedge( i, (++match) + 50, 1 );
else
{
addedge( i, (++match) + 50, 1 );
addedge( j, match + 50, 1 );
}
}
}
for (int i = 1; i <= match; i++)
{
addedge( i + 50, des, 1 );
}
if (Dinic() < (n*(n-1))/2) low = mid + 1;
else
{
ans = mid;
high = mid - 1;
}
}
cout << n - ans + 1 << endl;
}
return 0;
}
解题报告 之 POJ2699 The Maximum Number of Strong Kings
标签:
原文地址:http://blog.csdn.net/maxichu/article/details/45269497