题意:有n(n<=10)个选手,两两之间打比赛,共有n*(n-1)/2场比赛,赢一场得1分。给出每个人最后的得分。求有多少个定义如下的strong king:赢了所有得分比自己高的人或本身就是分数最高的人。

更详细的说明:https://blog.csdn.net/sdj222555/article/details/7797257

分析:因为n很小,枚举人数是一种可行的做法,网络流求解。具体的建图方法是:

1.从源点向每个选手i建一条容量为val[i]的弧;

2.将每场比赛视作点,由每场比赛向汇点建一条容量为1的弧;

3.一对选手i和j之间,若val[i]<val[j]且i是 strong king,那么i向该场比赛的编号建一条容量为1的弧,表示i赢下了该场比赛。

跑出最大流f,若f等于比赛数,说明该情况下能得到正确比赛结果。

最暴力的方法是二进制枚举可能的strong king情况,复杂度能够接受。而链接博客中给出的做法却是十分精妙的枚举。

#include<iostream>
#include<stdio.h>
#include<cstring>
#include<vector>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<cmath>
#include<algorithm>
using namespace std;
const int INF = 0x3f3f3f3f;
const int MAXN=1010;//点数的最大值
const int MAXM=400010;//边数的最大值
#define captype int struct SAP_MaxFlow{
struct EDGE{
int to,next;
captype cap;
}edg[MAXM];
int eid,head[MAXN];
int gap[MAXN];
int dis[MAXN];
int cur[MAXN];
int pre[MAXN]; void init(){
eid=0;
memset(head,-1,sizeof(head));
}
void AddEdge(int u,int v,captype c,captype rc=0){
edg[eid].to=v; edg[eid].next=head[u];
edg[eid].cap=c; head[u]=eid++;
edg[eid].to=u; edg[eid].next=head[v];
edg[eid].cap=rc; head[v]=eid++;
}
captype maxFlow_sap(int sNode,int eNode, int n){//n是包括源点和汇点的总点个数,这个一定要注意
memset(gap,0,sizeof(gap));
memset(dis,0,sizeof(dis));
memcpy(cur,head,sizeof(head));
pre[sNode] = -1;
gap[0]=n;
captype ans=0;
int u=sNode;
while(dis[sNode]<n){
if(u==eNode){
captype Min=INF ;
int inser;
for(int i=pre[u]; i!=-1; i=pre[edg[i^1].to])
if(Min>edg[i].cap){
Min=edg[i].cap;
inser=i;
}
for(int i=pre[u]; i!=-1; i=pre[edg[i^1].to]){
edg[i].cap-=Min;
edg[i^1].cap+=Min;
}
ans+=Min;
u=edg[inser^1].to;
continue;
}
bool flag = false;
int v;
for(int i=cur[u]; i!=-1; i=edg[i].next){
v=edg[i].to;
if(edg[i].cap>0 && dis[u]==dis[v]+1){
flag=true;
cur[u]=pre[v]=i;
break;
}
}
if(flag){
u=v;
continue;
}
int Mind= n;
for(int i=head[u]; i!=-1; i=edg[i].next)
if(edg[i].cap>0 && Mind>dis[edg[i].to]){
Mind=dis[edg[i].to];
cur[u]=i;
}
gap[dis[u]]--;
if(gap[dis[u]]==0) return ans;
dis[u]=Mind+1;
gap[dis[u]]++;
if(u!=sNode) u=edg[pre[u]^1].to; //退一条边
}
return ans;
}
}F; char str[1000];
int val[20];
int id[12][12];
int n,m,s,t;
bool vis[12][12]; void input()
{
n = 0;
int len = strlen(str);
int w=0;
for(int i=0;i<len;++i){
if(str[i]>='0' && str[i]<='9'){
w = w*10 + str[i]-'0';
if(i==len-1 || str[i+1]==' '){
val[++n] = w;
w = 0;
}
}
}
} void build(int k)
{
F.init();
for(int i = 1; i <= n; i++) F.AddEdge(s, i, val[i]);
for(int i = n + 1; i <= m; i++) F.AddEdge(i, t, 1);
memset(vis, 0, sizeof(vis));
for(int i = n - k + 1; i <= n; i++)
for(int j = i + 1; j <= n; j++)
if(val[i] < val[j])
F.AddEdge(i, id[i][j], 1), vis[i][j] = 1;
for(int i = 1; i <= n; i++){
for(int j = i + 1; j <= n; j++){
if(!vis[i][j]){
F.AddEdge(i, id[i][j], 1);
F.AddEdge(j, id[i][j], 1);
}
}
}
} int main()
{
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
freopen("out.txt","w",stdout);
#endif
int T; scanf("%d",&T);
getchar();
while(T--){
gets(str);
input();
m = n;
for(int i=1;i<=n;++i){
for(int j=i+1;j<=n;++j){
id[i][j] = id[j][i] = ++m;
}
}
int ans = 0;
s =0 ,t = m+1;
for(int i=n;i>=1;--i){
build(i);
if(F.maxFlow_sap(s,t,t+1)==n*(n-1)/2){
ans = i;
break;
}
}
printf("%d\n",ans);
}
return 0;
}

POJ - 2699 The Maximum Number of Strong Kings (最大流+枚举)的更多相关文章

  1. POJ 2699 The Maximum Number of Strong Kings Description

    The Maximum Number of Strong Kings   Description A tournament can be represented by a complete graph ...

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

    http://poj.org/problem?id=2699 题意: 一场联赛可以表示成一个完全图,点表示参赛选手,任意两点u, v之间有且仅有一条有向边(u, v)或( v, u),表示u打败v或v ...

  3. poj 2699 The Maximum Number of Strong Kings 枚举 最大流

    题目链接 题意 对于一个竞赛图(有向完全图),其顶点是选手,边是比赛,边\(e=(u,v)\)代表该场比赛中\(u\)战胜\(v\). 现定义选手的分数为其战胜的人的个数(即竞赛图中点的出度).并且定 ...

  4. poj 2699 The Maximum Number of Strong Kings【最大流+枚举】

    因为n很小所以从大到小枚举答案.(从小到大先排个序,因为显然胜利场次越多越容易成为strong king.然后对于每个枚举出来的ans建图.点分别表示人和比赛.s向所有人连接流量为胜利场次的边,所有比 ...

  5. POJ 2699 The Maximum Number of Strong Kings ——网络流

    一定存在一种最优方案,使得分数前几个人是SK 所以我们可以二分答案或者枚举,然后就是经典的网络流建模. 另:输入很Excited #include <cstdio> #include &l ...

  6. POJ2699:The Maximum Number of Strong Kings(枚举+贪心+最大流)

    The Maximum Number of Strong Kings Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 2488 ...

  7. POJ2699 The Maximum Number of Strong Kings

    Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 2102   Accepted: 975 Description A tour ...

  8. 【POJ2699】The Maximum Number of Strong Kings(网络流)

    Description A tournament can be represented by a complete graph in which each vertex denotes a playe ...

  9. 【POJ】【2699】The Maximum Number of Strong Kings

    网络流/最大流/二分or贪心 题目大意:有n个队伍,两两之间有一场比赛,胜者得分+1,负者得分+0,问最多有几只队伍打败了所有得分比他高的队伍? 可以想到如果存在这样的“strong king”那么一 ...

随机推荐

  1. MyBitis(iBitis)系列随笔之四:多表(多对一查询操作)

      前面几篇博客介绍的都是单表映射的一些操作,然而在我们的实际项目中往往是用到多表映射.至于多表映射的关键要用到mybitis的association来加以实现.          这篇介绍的是多表中 ...

  2. jQuery的end()方法使用详解

    end()方法的定义和用法: end()方法能够回到最近的一个"破坏性"操作之前,即将匹配的元素列表变为前一次的状态.如果没有破坏性操作将返回一个空集.破坏性操作的概念:指任何改变 ...

  3. MathType中怎么设置字体默认颜色

    MathType功能非常强大,在编辑公式时使用非常方便.利用MathType破解版不仅可以改变公式的字体和字号,也可以改变公式字体颜色.有时在编辑完成后需要对MathType公式格式全部进行修改,这时 ...

  4. STL容器:list双向链表学习

    list是一个双向列表容器,完成了标准C++数据结构中链表的所有功能; list与vector和deque类似,只不过其中的对象提供了对元素的随机访问. STL以双向链表的方式实现list,访问需要从 ...

  5. DataContractAttribute 类

    https://msdn.microsoft.com/zh-cn/library/system.runtime.serialization.datacontractattribute.aspx nam ...

  6. C# winform 中MessageBox用法大全(附效果图)

    我们在程序中经常会用到MessageBox. MessageBox.Show()共有21中重载方法.现将其常见用法总结如下: 1.MessageBox.Show(“Hello~~~~”); 最简单的, ...

  7. JQuery------实现点击左右按钮,切换图片功能

    如图: 代码: html @*商品主图片*@ <div class="product-img" style="display:table-cell;width:40 ...

  8. windows系统添加服务命令

    管理员身份进入cmd sc create TestSvr binPath= D:\Program Files\test.exe start= auto

  9. php实现简单的权限管理

    今天主要来实现一个权限管理系统,它主要是为了给不同的用户设定不同的权限,从而实现不同权限的用户登录之后使用的功能不一样,首先先看下数据库 总共有5张表,qx_user,qx_rules和qx_jues ...

  10. 设置 SSH Key 登录服务器和 Git 服务器

    设置 SSH Key 登录服务器 通过 ssh 登录服务器,一直都是用的账号和密码,今天看到一篇文章说这样不安全,使用 ssh key 的方式登录则是更好的选择,因此,研究实践了一下,并记录在这里. ...