poj2699 The Maximum Number of Strong Kings

177 篇文章 1 订阅
125 篇文章 0 订阅

Language: The Maximum Number of Strong Kings Time Limit:
1000MS Memory Limit: 65536K Total Submissions: 2114 Accepted: 977
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.

首先可以二分答案,然后可以发现,对于二分的答案x,选择最大的x个一定不会使答案更差。
这样我们就钦定了一些比赛的结果,用赢家连向比赛。剩下的比赛用双方连,最后检查是否满流。

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int s=105,t=106,oo=0x3f3f3f3f;
int a[110],fir[110],ne[500],to[500],w[500],
que[110],f[110],num[15][15],
n,tot;
void add(int u,int v,int x)
{
    tot++;
    ne[tot*2]=fir[u];
    fir[u]=tot*2;
    to[tot*2]=v;
    w[tot*2]=x;
    ne[tot*2+1]=fir[v];
    fir[v]=tot*2+1;
    to[tot*2+1]=u;
    w[tot*2+1]=0;
}
int rd(int &x)
{
    x=0;
    char c=getchar();
    while (c<'0'||c>'9')
    {
        if (c=='\n') return 0;
        c=getchar();
    }
    while (c>='0'&&c<='9')
    {
        x=x*10+c-'0';
        c=getchar();
    }
    if (c=='\n') return 2;
    return 1;
}
void init()
{
    int i,x;
    n=0;
    do
    {
        x=rd(a[n+1]);
        if (!(x+n)) x=rd(a[n+1]);
        if (x) n++;
    }
    while (x==1);
}
bool find()
{
    int i,j,u,v,hd=1,tl=1;
    que[1]=s;
    memset(f,0,sizeof(f));
    f[s]=1;
    while (hd<=tl)
    {
        u=que[hd++];
        for (i=fir[u];i;i=ne[i])
          if (w[i]&&!f[v=to[i]])
          {
            f[v]=f[u]+1;
            que[++tl]=v;
          }
    }
    return f[t];
}
int dfs(int u,int lim)
{
    int i,v,x,ret=0;
    if (u==t) return lim;
    for (i=fir[u];i&&ret<lim;i=ne[i])
      if (w[i]&&f[v=to[i]]==f[u]+1)
      {
        x=dfs(v,min(lim-ret,w[i]));
        ret+=x;
        w[i]-=x;
        w[i^1]+=x;
      }
    if (!ret) f[u]=0;
    return ret;
}
bool ok(int x)
{
    int i,j;
    memset(fir,0,sizeof(fir));
    tot=0;
    for (i=1;i<=n;i++)
      for (j=i+1;j<=n;j++)
        if (i>=n-x+1&&a[i]<a[j])
          add(i,num[i][j],1);
        else
        {
            add(i,num[i][j],1);
            add(j,num[i][j],1);
        }
    for (i=1;i<=n;i++)
      for (j=i+1;j<=n;j++)
        add(num[i][j],t,1);
    for (i=1;i<=n;i++)
      add(s,i,a[i]);
//  printf("check:%d\n",x);
//  for (i=1;i<=106;i++)
//    for (j=fir[i];j;j=ne[j])
//      if (w[j])
//        printf("%d->%d:%d\n",i,to[j],w[j]);
    while (find())
      while (dfs(s,oo));
    for (i=fir[s];i;i=ne[i])
      if (w[i]) return 0;
    return 1;
}
int main()
{
//  freopen("in.txt","r",stdin);
    int xx=10,i,j;
    for (i=1;i<=10;i++)
      for (j=i+1;j<=10;j++)
        num[i][j]=++xx;
    int T,l,r,mid;
    scanf("%d",&T);
    while (T--)
    {
        init();
        l=1;
        r=n;
        while (l<r)
        {
            mid=(l+r+1)/2;
            if (ok(mid)) l=mid;
            else r=mid-1;
        }
        printf("%d\n",l);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值