POJ-2699-网络流,枚举

题目大意:有n个人,两两之间进行比赛,一个如果击败了所有分数比他高的人或者自己本身就是分数最高的人,那么他就是sp,给出所有人的得分情况,问最多有多少个sp;

题目解析:构图,源->人->比赛->汇,源到人的容量就是每个人的得分情况,比赛到汇容量就是1;看到n最多就是10,我们可以枚举sp的个数为x,那么分数高的前x名就是sp,那么枚举人到比赛的时候,如果那个人是后x名,并且它的对手分数高于他,那么就从他连向比赛,对手不连,其余情况两个人都要连比赛;

AC代码:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<string>
#include<vector>
#include<queue>
using namespace std;
const int inf=0x3fffffff;        
const int maxn=1000;        
struct node        
{        
    int to,cap,rev;         
    node(int a,int b,int c)        
    {        
        to=a;        
        cap=b;        
        rev=c;        
    }        
};     
struct edge  
{  
    int to,cap;  
    edge(int a,int b)  
    {  
        to=a;  
        cap=b;  
    }  
};  
vector<node>vec[maxn];     
vector<edge>tor[maxn];       
int pre[maxn],iter[maxn],graph[301][301],n;      
bool vis[maxn];      
bool used[301][301];  
void add_edge(int from,int to,int cost)        
{        
    vec[from].push_back(node(to,cost,vec[to].size()));        
    vec[to].push_back(node(from,cost,vec[from].size()-1));        
}        
void bfs(int s){        
    memset(pre,-1,sizeof(pre));        
    queue<int>que;        
    pre[s]=0;que.push(s);        
    while(!que.empty()){        
        int v=que.front();que.pop();        
        for(int i=0;i<vec[v].size();i++){        
            node &e=vec[v][i];        
            if(e.cap>0&&pre[e.to]<0){        
                pre[e.to]=pre[v]+1;        
                que.push(e.to);        
            }        
        }        
    }        
}        
int dfs(int v,int t,int f){        
    if(v==t) return f;        
    for(int &i=iter[v];i<vec[v].size();i++){        
        node &e=vec[v][i];        
        if(e.cap>0&&pre[v]<pre[e.to]){        
            int d=dfs(e.to,t,min(f,e.cap));        
            if(d>0){        
                e.cap-=d;        
                vec[e.to][e.rev].cap+=d;        
                return d;        
            }        
        }        
    }        
    return 0;        
}        
int max_flow(int u,int v)        
{        
    int flow=0;        
    while(1)            
    {        
        bfs(u);      
        if(pre[v]<0)    return flow;      
        memset(iter,0,sizeof(iter));        
        int f;        
        while((f=dfs(u,v,inf))>0) flow+=f;        
    }        
} 
int score[110],cpt[12][12],cnt;
void build(int s,int t,int num)
{
	int i,j;
	for(i=0;i<maxn;i++)	vec[i].clear();
	for(i=1;i<=n;i++)
		add_edge(s,i,score[i]);
	for(i=n+1;i<=cnt+n;i++)
		add_edge(i,t,1);
	for(i=1;i<=n;i++)
	{
		for(j=i+1;j<=n;j++)
		{
			if(score[i]<score[j]&&i>=n-num+1)
				add_edge(i,cpt[i][j]+n,1);
			else 
			{
				add_edge(i,cpt[i][j]+n,1);
				add_edge(j,cpt[i][j]+n,1);
			}
		}
	}
}
int main()
{
	int t,i,j;
	scanf("%d",&t);
	getchar();
	while(t--)
	{
		char s[30];
	 	n=0,cnt=0;
		gets(s);
		int x=0,l=strlen(s);;
		for(i=0;i<l;i++)
		{
            if (s[i]>='0' && s[i]<='9'){
                x=x*10+s[i]-'0';
                if (i==l-1 || s[i+1]==' ') score[++n]=x,x=0;
            }
		}
		for(i=1;i<=n;i++)
		{
			for(j=i+1;j<=n;j++)
			{
				cpt[i][j]=++cnt;
			}
		}
	 	for(i=n;i>=1;i--)
	 	{
	 		build(0,n+cnt+1,i);
	 		if(max_flow(0,n+cnt+1)==cnt)
	 		{	
		 		printf("%d\n",i);
		 		break;
		 	}
	 	}
	}
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值