首页 > 代码库 > POJ 2699 The Maximum Number of Strong Kings (最大流+枚举)

POJ 2699 The Maximum Number of Strong Kings (最大流+枚举)

http://poj.org/problem?id=2699

题意:

 一场联赛可以表示成一个完全图,点表示参赛选手,任意两点u, v之间有且仅有一条有向边(u, v)或( v, u),表示u打败v或v打败u。一个选手的得分等于被他打败的选手总数。一个选手被称为“strong king”当且仅当他打败了所有比他分高的选手。分数最高的选手也是strong king。现在给出某场联赛所有选手的得分序列,由低到高,问合理安排每场比赛的结果后最多能有几个strong king。已知选手总数不超过10个。

 

思路:

选手总数很少,我们可以考虑枚举。

枚举当前strong king的个数为num个,那么可能存在分数最高的num个人是strong king,其余情况也可能存在,但这种情况是最可能的,只要满足这个就可以了。

建立源点和汇点,源点和每场比赛相连(比赛共有n*(n-1)/2场),容量为1,汇点和选手相连,容量为选手分数。

那么比赛和选手怎么连接呢?
如果选手i是strong king,那么凡是分数比他高的人,他都必须要赢,此时把这场比赛和i相连。

如果i和j都不是strong king,那么这场比赛无所谓谁输谁赢,将这场比赛和i和j都连起来就可以。

最后跑最大流,如果等于n*(n-1)/2,就是可以的。

  1 #include<iostream>  2 #include<algorithm>  3 #include<cstring>  4 #include<cstdio>  5 #include<sstream>  6 #include<vector>  7 #include<stack>  8 #include<queue>  9 #include<cmath> 10 #include<map> 11 using namespace std; 12 typedef long long LL; 13 typedef pair<int,int> pll; 14 const int INF=0x3f3f3f3f; 15 const int maxn=300+5; 16  17 int n; 18 int score[maxn]; 19 int com[maxn][maxn]; 20  21 struct Edge 22 { 23     int from,to,cap,flow; 24     Edge(int u,int v,int w,int f):from(u),to(v),cap(w),flow(f){} 25 }; 26  27 struct Dinic 28 { 29     int n,m,s,t; 30     vector<Edge> edges; 31     vector<int> G[maxn]; 32     bool vis[maxn]; 33     int cur[maxn]; 34     int d[maxn]; 35  36     void init(int n) 37     { 38         this->n=n; 39         for(int i=0;i<n;++i) G[i].clear(); 40         edges.clear(); 41     } 42  43     void AddEdge(int from,int to,int cap) 44     { 45         edges.push_back( Edge(from,to,cap,0) ); 46         edges.push_back( Edge(to,from,0,0) ); 47         m=edges.size(); 48         G[from].push_back(m-2); 49         G[to].push_back(m-1); 50     } 51  52     bool BFS() 53     { 54         queue<int> Q; 55         memset(vis,0,sizeof(vis)); 56         vis[s]=true; 57         d[s]=0; 58         Q.push(s); 59         while(!Q.empty()) 60         { 61             int x=Q.front(); Q.pop(); 62             for(int i=0;i<G[x].size();++i) 63             { 64                 Edge& e=edges[G[x][i]]; 65                 if(!vis[e.to] && e.cap>e.flow) 66                 { 67                     vis[e.to]=true; 68                     d[e.to]=d[x]+1; 69                     Q.push(e.to); 70                 } 71             } 72         } 73         return vis[t]; 74     } 75  76     int DFS(int x,int a) 77     { 78         if(x==t || a==0) return a; 79         int flow=0, f; 80         for(int &i=cur[x];i<G[x].size();++i) 81         { 82             Edge &e=edges[G[x][i]]; 83             if(d[e.to]==d[x]+1 && (f=DFS(e.to,min(a,e.cap-e.flow) ) )>0) 84             { 85                 e.flow +=f; 86                 edges[G[x][i]^1].flow -=f; 87                 flow +=f; 88                 a -=f; 89                 if(a==0) break; 90             } 91         } 92         return flow; 93     } 94  95     int Maxflow(int s,int t) 96     { 97         this->s=s; this->t=t; 98         int flow=0; 99         while(BFS())100         {101             memset(cur,0,sizeof(cur));102             flow +=DFS(s,INF);103         }104         return flow;105     }106 }DC;107 108 int solve(int num,int cnt)109 {110     int tot=n*(n-1)/2;111     int src=http://www.mamicode.com/0,dst=n+tot+1;112     DC.init(dst+1);113 114     for(int i=1;i<=n;i++)115         DC.AddEdge(i,dst,score[i]);116     for(int j=n+1;j<=cnt;j++)117         DC.AddEdge(src,j,1);118 119     for(int i=1;i<=n;i++)120         for(int j=i+1;j<=n;j++)121     {122         if(score[i]>score[j] && j>n-num)   DC.AddEdge(com[i][j],j,1);123         else if(score[i]<score[j] && i>n-num)  DC.AddEdge(com[i][j],i,1);124         else125         {126             DC.AddEdge(com[i][j],i,1);127             DC.AddEdge(com[i][j],j,1);128         }129     }130     return DC.Maxflow(src,dst)==tot;131 }132 133 int main()134 {135     //freopen("D:\\input.txt","r",stdin);136     int T;137     scanf("%d",&T);138     getchar();139     while(T--)140     {141         n=0;142         string str;143         getline(cin,str);144         stringstream ss(str);145         int x;146         while(ss>>x)  score[++n]=x;147 148         int num=n;149         for(int i=1;i<=n;i++)150             for(int j=i+1;j<=n;j++)151             com[i][j]=com[j][i]=++num;152 153 154         for(int i=n;i>=0;i--)155         {156             if(solve(i,num))  {printf("%d\n",i);break;}157         }158     }159     return 0;160 }

 

POJ 2699 The Maximum Number of Strong Kings (最大流+枚举)