http://poj.org/problem?id=2699
题意:
有n(n<=10)个竞赛者,进行了n*(n-1)/2次的比赛。已知每一个竞赛者在比赛中胜利的次数a1、a2、a3……..an。(次序列是从小到大排序的),问你这n个人中最强的竞赛者最多有几个。(如果这个竞赛者胜利的次数最多或这个竞赛者打败了所有胜利次数比他多的竞赛者,那么这个竞赛者就是最强的。其中每两个人有且仅进行一场比赛。)
思路:
k从n枚举到1 源点到每个人连边 流为ai 必须胜得和对应比赛连 流1 随便的两个人都连向他俩的那场比赛 比赛和汇点连1 最大流是总比赛数目的话 说明这个k可以 另外,很多题解上说枚举的是从序列最后一个开始连续K个为最强的,为什么前面的不可能出现最强的?其实我觉得不是,而如果k是答案的话,选取k个当前分最高的肯定可以实现,虽然选更小的也有可能。但既然我们找最大的,那一定这么找最完美,还要注意输入格式,很多个空格,因此tle了一次
#include <cstdio>
#include <iostream>
#include <cstring>
#include <queue>
const int INF = (1<<30);
using namespace std;
int a[20],n,tot,head[1010];
int level[1100],S,T;
struct node{
int v,cap,next;
}node[10010*4];
void add(int s,int t,int cap) {
node[tot].v=t;node[tot].cap=cap;node[tot].next = head[s];
head[s] = tot++;
node[tot].v=s;node[tot].cap=0;node[tot].next = head[t];
head[t]=tot++;
}
void init(){
int cc = 1;
char s[1100];
gets(s);
int pp = 0,len = strlen(s);
for(int i = 0 ; i < len;i++)
if(s[i] >= '0' && s[i] <= '9'){
pp = pp*10+s[i]-'0';
if(i == len-1 || s[i+1] == ' '){
a[cc++] = pp; pp = 0;
}
}
n = cc-1;
}
int bfs(){
int q[1100];
int t = 0,w =0;
memset(level,-1,sizeof(level));
q[w++] = S;
level[S] = 0;
while(t<w){
int u = q[t++];
for(int k = head[u];k != -1 ;k = node[k].next){
int v = node[k].v;
int cap = node[k].cap;
if(cap > 0 && level[v] == -1){
level[v] = level[u]+1;
q[w++] = v;
}
}
}
return level[T] != -1;
}
int dfs(int s,int c){
if(s == T) return c;
int temp;
for(int k = head[s];k!=-1;k = node[k].next){
int v = node[k].v;
int cap = node[k].cap;
if(cap > 0 && level[v] == level[s]+1 && (temp = dfs(v,min(cap,c)))>0){
node[k].cap -= temp;
node[k^1].cap += temp;
return temp;
}
}
return 0;
}
int dinic(){
int maxflow = 0,flow;
while(bfs()){
while(flow = dfs(S,INF))
maxflow += flow;
}
return maxflow;
}
void sov(){
for(int cnt = n ; cnt > 0 ; cnt--){
tot = 0 ;
memset(head,-1,sizeof(head));
for(int i = 1 ; i <= n ;i++)
add(S,i,a[i]);
for(int i = 1; i <= n ;i++)
for(int j = i+1;j <= n ;j++){
add(i*n+j,T,1);
if(i > n-cnt&&a[j] > a[i])
add(i,i*n+j,1);
else{
add(i,i*n+j,1);
add(j,i*n+j,1);
}
}
int ans = dinic();
if(ans == n*(n-1)/2){
printf("%d\n",cnt);
return;
}
}
}
int main(){
int ca;
S = 0;
T = 101;
scanf("%d ",&ca);
while(ca--){
init();
sov();
}
}