[省选前题目整理][POJ 2699]The Maximum Number of Strong Kings(暴力枚举+最大流)
2015-03-29 18:47
519 查看
题目链接
http://poj.org/problem?id=2699题目大意
n个人比赛, 两两比,共n(n-1)场比赛, 赢的人得1分, n<=10。如果一个人打败了所有比自己分数高的人, 或者他本身就是分数最高的, 那么他就是StrongKing。可能有多个Strong King, 现在按非降的顺序给你每个人的得分(不难道想到容量把), 问Strong King最多能有几个。思路
显然n个人之间的比赛关系可以构成一个竞赛图。竞赛图问题往往可以用网络流解决,此题也是如此。鉴于某个答案的猜测值的可行性随着答案大小单调改变,很自然地想到用二分来解决此题。那么我们就要二分Strong King的个数ans。下面的问题变成了,已知Strong King的个数ans,求这个答案是否大于实际答案(不成立)。不妨把每个人看成一个个点(如下图的蓝色点),每个比赛也看成一个个点(如下图的绿色点)。每个比赛向T连容量为1的边(表示赢得一场比赛能得到1分),S向每个人连容量为该人获得分数的边(表示这个人最多只能赢这么多分)。
然后对于后ans个人来说,由于输入的分数是升序的,因此它们是我们假定的Strong Kings。在这些人中,如果人i的分比人j低,那么就从人i向这两个人的比赛对应的点连容量为1的边(显然i和j的胜负已定,根据规则,i比j的分低,而i也是Strong King,那么一定是i赢了这场比赛)。对于所有人来说,任意两个人a、b,分别向他们之间的比赛对应的点连容量为1的边(表明对于其他人来说,他们既可以赢,也可以输)。
最终这个图的最大流就是在Strong Kings个数为ans的情况下能够进行的比赛场数(所有人的分数之和),显然比赛场数是n*(n-1)场,若最大流不等于n*(n-1),那么就表明Strong Kings个数为ans的情况是不合法的。
代码
#include <sstream> #include <string> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <algorithm> #define MAXV 1000 #define MAXE 3000 #define MAXN 1000 #define INF 0x3f3f3f3f using namespace std; int S,T; struct edge { int u,v,cap,next; }edges[MAXE]; int head[MAXV],nCount=1; void AddEdge(int U,int V,int C) { edges[++nCount].u=U; edges[nCount].v=V; edges[nCount].cap=C; edges[nCount].next=head[U]; head[U]=nCount; } void add(int U,int V,int C) { AddEdge(U,V,C); AddEdge(V,U,0); } int layer[MAXV],q[MAXE*2]; bool CountLayer() { memset(layer,-1,sizeof(layer)); int h=0,t=1; q[h]=S; layer[S]=1; while(h<t) { int u=q[h++]; for(int p=head[u];p!=-1;p=edges[p].next) { int v=edges[p].v; if(layer[v]==-1&&edges[p].cap) { layer[v]=layer[u]+1; q[t++]=v; } } } return layer[T]!=-1; } int DFS(int u,int flow) { if(u==T) return flow; int used=0; for(int p=head[u];p!=-1;p=edges[p].next) { int v=edges[p].v; if(layer[v]==layer[u]+1&&edges[p].cap) { int tmp=DFS(v,min(flow-used,edges[p].cap)); used+=tmp; edges[p].cap-=tmp; edges[p^1].cap+=tmp; if(used==flow) return used; } } if(!used) layer[u]=-1; return used; } int Dinic() { int maxflow=0; while(CountLayer()) maxflow+=DFS(S,INF); return maxflow; } int n=0,tot=0; int match[MAXN][MAXN],score[MAXN]; bool matched[MAXN*MAXN]; char s[MAXN]; bool check(int x) //已知有x个Strong Kings { S=MAXV-2,T=MAXV-1; nCount=1; memset(head,-1,sizeof(head)); memset(matched,false,sizeof(matched)); for(int i=1;i<=n;i++) add(S,i,score[i]); for(int i=1;i<=tot;i++) add(i+n,T,1); for(int i=n-x+1;i<=n;i++) for(int j=i+1;j<=n;j++) if(score[j]>score[i]) { matched[match[i][j]]=true; add(i,match[i][j]+n,1); } for(int i=1;i<=n;i++) for(int j=i+1;j<=n;j++) if(!matched[match[i][j]]) { add(i,match[i][j]+n,1); add(j,match[i][j]+n,1); } return Dinic()==(n*(n-1)/2); } int main() { int TestCase; scanf("%d",&TestCase); getchar(); //!!!! while(TestCase--) { memset(head,-1,sizeof(head)); nCount=1; n=0,tot=0; int tmp; gets(s); stringstream str(s); while(str>>tmp) score[++n]=tmp; for(int i=1;i<=n;i++) for(int j=i+1;j<=n;j++) match[i][j]=++tot; int ans; for(int i=n;i>=1;i--) if(check(i)) { ans=i; break; } printf("%d\n",ans); } return 0; }
相关文章推荐
- POJ 2699 The Maximum Number of Strong Kings 最大流 枚举
- POJ 2699 The Maximum Number of Strong Kings(枚举+最大流)
- POJ 2699 The Maximum Number of Strong Kings (最大流+枚举)
- POJ 2699 - The Maximum Number of Strong Kings(网络流‘最大流)
- POJ 2699 The Maximum Number of Strong Kings 竞赛图+最大流
- POJ 2699 The Maximum Number of Strong Kings(最大流)
- POJ 2699 The Maximum Number of Strong Kings(最大流)
- poj 2699 The Maximum Number of Strong Kings【最大流+枚举】
- poj 2699 The Maximum Number of Strong Kings(最大流,建图)
- POJ 2699 The Maximum Number of Strong Kings 最大流
- POJ 2699 The Maximum Number of Strong Kings(最大流)
- poj 2699 The Maximum Number of Strong Kings
- poj2699 The Maximum Number of Strong Kings
- poj 2699 The Maximum Number of Strong Kings 【二分 + 竞赛图建模判断是否满流】
- POJ 2699 The Maximum Number of Strong Kings (网络流)
- poj 2699 The Maximum Number of Strong Kings 网络流
- 【POJ】【2699】The Maximum Number of Strong Kings
- POJ 2699 The Maximum Number of Strong Kings 网络流 竞赛图
- poj 2699 The Maximum Number of Strong Kings
- POJ 2699 The Maximum Number of Strong Kings ——网络流