赞
踩
Time Limit: 1000MS | Memory Limit: 65536K | |
Total Submissions: 1842 | Accepted: 862 |
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
题意是给你他们每个人的胜场数,问有多少最强竞赛者(指的如果胜场是最多的。或者赢了所有胜利数比他多的)
本来想二分胜利场数,后来想想不对。需要二分胜利人数
然后是建图:
超级源点连向人的流量是人的胜利场数
比赛连向超级汇点的流量是1
人连向比赛的流量是1 这里需要考虑如果这个人比另外一个人比赛场数低,且也在最强者里面,那么这把比赛他必须赢,所以只能连这个人到比赛的连线,其他的话从这两个人,各连一条到比赛,代表他们都能够去赢这场比赛。
因为数据比较小,我直接暴力枚举了。。并没有用二分。。。
- #include <iostream>
- #include <cstdio>
- #include <climits>
- #include <cstring>
- #include <cstdlib>
- #include <cmath>
- #include <vector>
- #include <queue>
- #include <algorithm>
- #define esp 1e-6
- #define inf 0x0f0f0f0f
- #define LL long long
- using namespace std;
-
- const int MAXN = 100010 ; //点数最大值
- const int MAXM = 400010 ; //边数最大值
- const int INF = 0x3f3f3f3f;
-
- int M,TOL,S,V;
-
-
- struct Edge{
- int to,next,cap,flow;
- }edge[MAXM];//注意是MAXM
- int tol;
- int head[MAXN];
- int gap[MAXN],dep[MAXN],pre[MAXN],cur[MAXN];
- //int imap[333][333];
- int b[13],co[13][13];
-
-
- int cmp(int a,int b){
- return a>b;
- }
-
- void init(){
- tol = 0;
- memset(head,-1,sizeof(head));
- }
-
- void addedge(int u,int v,int w,int rw=0){
- edge[tol].to = v;
- edge[tol].cap = w;
- edge[tol].next = head[u];
- edge[tol].flow = 0;
- head[u] = tol++;
- edge[tol].to = u;
- edge[tol].cap = rw;
- edge[tol].next = head[v];
- edge[tol].flow = 0;
- head[v] = tol++;
- }
- //最大流开始
- int sap(int start,int end,int N){
- memset(gap,0,sizeof(gap));
- memset(dep,0,sizeof(dep));
- memcpy(cur,head,sizeof(head));
- int u = start;
- pre[u] = -1;
- gap[0] = N;
- int ans = 0;
- while(dep[start] < N){
- if(u==end){
- int Min = INF;
- for(int i=pre[u];i!= -1; i=pre[edge[i^1].to])
- if(Min > edge[i].cap - edge[i].flow)
- Min = edge[i].cap - edge[i].flow;
-
- for(int i=pre[u];i!=-1;i=pre[edge[i^1].to]){
- edge[i].flow += Min;
- edge[i^1].flow -=Min;
- }
- u=start;
- ans +=Min;
- continue;
- }
- bool flag = false;
- int v;
- for(int i= cur[u];i!=-1;i=edge[i].next){
- v=edge[i].to;
- if(edge[i].cap-edge[i].flow&&dep[v]+1==dep[u]){
- flag=true;
- cur[u]=pre[v]=i;
- break;
- }
- }
- if(flag){
- u=v;
- continue;
- }
- int Min = N;
- for(int i=head[u];i!= -1;i=edge[i].next)
- if(edge[i].cap-edge[i].flow&&dep[edge[i].to]<Min){
- Min=dep[edge[i].to];
- cur[u] = i;
- }
- gap[dep[u]]--;
- if(!gap[dep[u]]) return ans;
- dep[u] = Min +1;
- gap[dep[u]]++;
- if(u!=start) u = edge[pre[u]^1].to;
- }
- return ans;
- }
- //最大流结束
-
- //构图
- void build(int mid){
- int i,j;
- S=TOL+1;
- V=TOL+2;
- //超级源点 到每个人
- for(i=0;i<M;i++){
- addedge(S,i,b[i]);
- }
- //每场比赛到超级汇点
- for(i=0;i<M;i++){
- for(j=i+1;j<M;j++){
- addedge(co[i][j],V,1);
- }
- }
- //人到比赛
- for(i=0;i<M;i++){
- for(j=i+1;j<M;j++){
- if(i<mid&&j<mid){
- if(b[i]>b[j]){
- addedge(j,co[i][j],1);
- }
- else if(b[i]<b[j]){
- addedge(i,co[i][j],1);
- }
- else{
- addedge(j,co[i][j],1);
- addedge(i,co[i][j],1);
- }
- }
- else{
- addedge(j,co[i][j],1);
- addedge(i,co[i][j],1);
- }
- }
- }
-
- }
- //二分枚举解题
- bool solve(int mid){
- init();
- build(mid);
- int k=sap(S,V,V+1);
- // printf("k=%d\n",k);
- return k==TOL-M+1;
- }
- int main(){
- int i,j,k,l,m,n;
- int T;
- scanf("%d\n",&T);
- char a;
- while(T--){
- i=0;
- while(1){
- scanf("%c",&a);
- if(a=='\n'||a=='\0'){
- break;
- }
- else{
- if(a!=' '){
- b[i++]=a-'0';
- }
- }
- }
-
- //printf("%d\n",b[0]);
- M=i;
- sort(b,b+M,cmp);
- int num=M;
- // printf("M= %d\n",M);
- for(i=0;i<M;i++){
- for(j=i+1;j<M;j++){
- co[i][j]=num++;
- }
- }
- TOL=num-1;
- // printf("TOL= %d\n",TOL);
- // for(int aa=0;aa<M;aa++) printf("%d ",b[aa]);
-
- int l=0,orz;
- for(i=1;i<=M;i++){
- if(solve(i)){
- orz=i;
- }
- else break;
- }
- printf("%d\n",orz);
-
-
-
- }
-
-
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。