【LA2531 训练指南】足球联赛 【最大流】

题意:

  有n支队伍进行比赛,每支队伍需要打的比赛数目相同。每场比赛恰好一支队伍胜,另一支败。给出每支队伍目前胜的场数和败的场数,以及每两支队伍还剩下的比赛场数,确定所有可能的冠军的球队。(获胜场数最多的是冠军,可以并列)。

分析

  一只队伍如果可能得冠军,那么就一定可以通过调整,未来的几场比赛的结果使自己赢得场次最多。否则便不可能成为冠军。

   在判断第i支队伍有无可能成为冠军时:首先,第i支队伍得对局i全部取得胜利,得到i胜利的总场数为total。然后判断其他队伍的对局,能否互相限制使得,任何队伍胜利的场数都不超过total。

  建模方法:

 对每两支队伍(u,v)构造一个X结点,从S引一条弧过来,容量为这两支队伍还需要比赛的场数。对每支队伍u构造一个Y结点,引一条弧到T,容量为total-win[u].然后每个(u,v)结点向u和v结点个连一条无穷大得弧。这样当且仅当,从S出发得每条弧都是满载得时候,当前队伍才有可能得冠军。

  

  1 #include <cstdio>
  2 #include <cstring>
  3 #include <iostream>
  4 #include <algorithm>
  5 #include <queue>
  6 #include <vector>
  7 
  8 using namespace std;
  9 const int maxn=1000+10;
 10 const int MAXN=30;
 11 const int maxm=30000+100;
 12 const int INF=2147000000;
 13 struct Dinic{
 14     int head[maxn],Next[maxm],to[maxm],cap[maxm],flow[maxm],from[maxm];
 15     int sz,n,m,s,t;
 16     bool vis[maxn];
 17     int cur[maxn],d[maxn];
 18     void init(int n){
 19         this->n=n;
 20         memset(head,-1,sizeof(head));
 21         this->sz=-1;
 22     }
 23     void add_edge(int a,int b,int c){
 24         ++sz;
 25         to[sz]=b;
 26         cap[sz]=c;flow[sz]=0;from[sz]=a;
 27         Next[sz]=head[a];head[a]=sz;
 28         ++sz;
 29         to[sz]=a;
 30         cap[sz]=c;flow[sz]=c;from[sz]=b;
 31         Next[sz]=head[b];head[b]=sz;
 32     }
 33     bool BFS(){
 34         memset(vis,0,sizeof(vis));
 35         queue<int>Q;
 36         vis[s]=1;
 37         d[s]=0;
 38         Q.push(s);
 39         while(!Q.empty()){
 40             int u=Q.front();Q.pop();
 41             for(int i=head[u];i!=-1;i=Next[i]){
 42                 int v=to[i];
 43                 if(!vis[v]&&cap[i]>flow[i]){
 44                     vis[v]=1;
 45                     d[v]=d[u]+1;
 46                     Q.push(v);
 47                 }
 48             }
 49         }
 50         return vis[t];
 51    }
 52     int DFS(int x,int a){
 53         if(x==t||a==0)return a;
 54         int Flow=0,f;
 55         for(int& i=cur[x];i!=-1;i=Next[i]){
 56             int v=to[i];
 57             if(d[v]==d[x]+1&&(f=DFS(v,min(a,cap[i]-flow[i])))>0){
 58                 Flow+=f;
 59                 flow[i]+=f;
 60                 flow[i^1]-=f;
 61                 a-=f;
 62                 if(a==0)break;
 63             }
 64         }
 65         return Flow;
 66     }
 67     int Maxflow(int s,int t){
 68         this->s=s,this->t=t;
 69         int Flow=0;
 70         while(BFS()){
 71             for(int i=0;i<=n;i++)
 72              cur[i]=head[i];
 73             Flow+=DFS(s,INF);
 74         }
 75         return Flow;
 76     }
 77 }dinic;
 78 int T,n;
 79 int win[MAXN],lose[MAXN];
 80 int G[MAXN][MAXN];
 81 vector<int>ans;
 82 bool judge(int num){
 83     int total=win[num];
 84     for(int i=1;i<=n;i++){
 85         total+=G[num][i];
 86     }
 87     //cout<<total<<endl;
 88 
 89     int allS=(n*n-3*n+2)/2;
 90     int NUM=0;
 91     dinic.init(allS+n+2);
 92     dinic.s=0,dinic.t=allS+n+1;
 93     for(int i=1;i<=n;i++){
 94             if(i==num)continue;
 95         for(int j=i+1;j<=n;j++){
 96          //   cout<<i<<" "<<j<<" "<<G[i][j]<<endl;
 97             if(j==num)continue;
 98             NUM++;
 99             dinic.add_edge(0,NUM,G[i][j]);
100             dinic.add_edge(NUM,allS+i,INF);
101             dinic.add_edge(NUM,allS+j,INF);
102         }
103     }
104 
105     for(int i=1;i<=n;i++){
106         if(i==num)continue;
107         if(total<win[i])return false;
108         dinic.add_edge(allS+i,dinic.t,total-win[i]);
109     }
110     dinic.Maxflow(0,allS+n+1);
111     for(int i=0;i<=dinic.sz;i+=2){
112         if(dinic.from[i]==0){
113             if(dinic.flow[i]<dinic.cap[i])
114                 return false;
115         }
116     }
117     return true;
118 }
119 int main(){
120     scanf("%d",&T);
121     for(int t=1;t<=T;t++){
122        // if(t!=1)printf("\n");
123         ans.clear();
124         scanf("%d",&n);
125         for(int i=1;i<=n;i++){
126             scanf("%d%d",&win[i],&lose[i]);
127         }
128         for(int i=1;i<=n;i++){
129             for(int j=1;j<=n;j++){
130                 scanf("%d",&G[i][j]);
131             }
132         }
133        /* if(judge(1))
134             printf("Yes 1");*/
135 
136         for(int i=1;i<=n;i++){
137             if(judge(i))
138                 ans.push_back(i);
139         }
140         sort(ans.begin(),ans.end());
141         for(int i=0;i<ans.size();i++){
142             if(i!=0)printf(" ");
143             printf("%d",ans[i]);
144         }
145         printf("\n");
146     }
147 return 0;
148 }
View Code

 

posted @ 2018-07-13 12:42  蒟蒻LQL  阅读(295)  评论(0编辑  收藏  举报