poj2699:http://poj.org/problem?id=2699
题意:n个人,进行n*(n-1)/2场比赛,赢一场则得到一分。如果一个人打败了所有比他分数高的对手,或者他就是分数最高的,那么他就是strong kind。现在给你每个人的得分,问你最多有多少个strong kind。
题解:自己没有思路,看了别人的题解,才勉强理解了。首先,肯定让得分高的成为strong king,因为概率比较大,然后就是怎建图了。假如,我们已经知道了,有m个strong kind,那么这m个人一定是后m个,所以,我们只要判断这m个是否满足条件就可以了,由于n很小,所以可以直接枚举ans。接下来就是建图,人作为一个点,与s建立一边,容量就是得分,然后比赛作为一种点,和t连接,容量是1,然后开始枚举ans,对于后ans个人来说,每个人i对于比他分高的选手j,都必须赢,所以对于i,j之间的比赛,i必须赢,所以i--mp[i][j](表示ij之间比赛的编号)建立一边,容量是1,然后对于剩余的比赛来说,i,j都可以赢,所以i,j都要建立一边到mp[i][j]容量是1,然后跑网络流,如果跑出的maxflow==n*(n-1)/2,说明这种方式是满足的,直接输出就可以了。这一题的读入不是很规范,数字之间不是严格的一个空格,可能有多个空格。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<iostream> 2 #include<cstring> 3 #include<algorithm> 4 #include<cstdio> 5 #include<queue> 6 #include<string> 7 #define INF 100000000 8 using namespace std; 9 const int N=125; 10 const int M=500; 11 struct Node{ 12 int v; 13 int f; 14 int next; 15 }edge[M]; 16 int n,m,u,v,tt,cnt,sx,ex; 17 int head[125],pre[125]; 18 int g[12],f[N],mp[12][12];//根据题目要求申请 19 void init(){ 20 cnt=0; 21 memset(head,-1,sizeof(head)); 22 memset(f,0,sizeof(f)); 23 } 24 void add(int u,int v,int w){ 25 edge[cnt].v=v; 26 edge[cnt].f=w; 27 edge[cnt].next=head[u]; 28 head[u]=cnt++; 29 edge[cnt].f=0; 30 edge[cnt].v=u; 31 edge[cnt].next=head[v]; 32 head[v]=cnt++; 33 } 34 bool BFS(){ 35 memset(pre,0,sizeof(pre)); 36 pre[sx]=1; 37 queue<int>Q; 38 Q.push(sx); 39 while(!Q.empty()){ 40 int d=Q.front(); 41 Q.pop(); 42 for(int i=head[d];i!=-1;i=edge[i].next ){ 43 if(edge[i].f&&!pre[edge[i].v]){ 44 pre[edge[i].v]=pre[d]+1; 45 Q.push(edge[i].v); 46 } 47 } 48 } 49 return pre[ex]>0; 50 } 51 int dinic(int flow,int ps){ 52 int f=flow; 53 if(ps==ex)return f; 54 for(int i=head[ps];i!=-1;i=edge[i].next){ 55 if(edge[i].f&&pre[edge[i].v]==pre[ps]+1){ 56 int a=edge[i].f; 57 int t=dinic(min(a,flow),edge[i].v); 58 edge[i].f-=t; 59 edge[i^1].f+=t; 60 flow-=t; 61 if(flow<=0)break; 62 } 63 64 } 65 if(f-flow<=0)pre[ps]=-1; 66 return f-flow; 67 } 68 int solve(){ 69 int sum=0; 70 while(BFS()) 71 sum+=dinic(INF,sx); 72 return sum; 73 } 74 void build(int num){ 75 init(); 76 for(int i=1;i<=n;i++) 77 add(0,i,g[i]); 78 for(int i=1;i<=tt;i++) 79 add(i+n,n+tt+1,1); 80 for(int i=n-num+1;i<=n;i++) 81 for(int j=i+1;j<=n;j++){ 82 if(g[j]>g[i]){ 83 f[mp[i][j]]=1; 84 add(i,mp[i][j]+n,1); 85 } 86 } 87 for(int i=1;i<=n;i++) 88 for(int j=i+1;j<=n;j++){ 89 if(!f[mp[i][j]]){ 90 add(i,mp[i][j]+n,1); 91 add(j,mp[i][j]+n,1); 92 } 93 } 94 } 95 string str; 96 int main() { 97 int T; 98 scanf("%d",&T); 99 getchar(); 100 while(T--) { 101 n=0; 102 getline(cin,str); 103 int len=str.length(); 104 for(int i=0;i<len;i++){ 105 if(str[i]>='0'&&str[i]<='9') 106 g[++n]=str[i]-'0'; 107 } 108 tt=0; 109 for(int i=1;i<=n;i++) 110 for(int j=i+1;j<=n;j++) 111 mp[i][j]=++tt; 112 sx=0,ex=n+tt+1; 113 int i; 114 for(i=n;i>1;i--){ 115 build(i); 116 if(solve()==tt)break; 117 } 118 printf("%d ",i); 119 } 120 return 0; 121 }