UVAlive2531 The K-League(最大流)

来源:互联网 发布:mac 命令行 文件夹 编辑:程序博客网 时间:2024/06/04 18:52
 

题目链接:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=33451

 

【思路】

       最大流。

       大体思路是枚举每个队伍,最大流判断是否可能成为冠军。

       构图:

       1 建立ST,比赛(u,v)建立n^2个结点,队伍u建立n个结点。

       2 由S向(u,v)连容量为a[u][v]的边,由(u,v)向u和v连容量为INF的边,由u向T连容量为total-w[u]的边。

       3 如果从S发出的边都满载则该team可行。

 

【代码】

 

  1 #include<cstdio>  2 #include<cstring>  3 #include<queue>  4 #include<vector>  5 #define FOR(a,b,c) for(int a=(b);a<(c);a++)  6 using namespace std;  7   8 const int maxn = 700+10;  9 const int INF = 1e9; 10  11 struct Edge{ 12     int u,v,cap,flow; 13 }; 14 struct Dinic { 15     int n,m,s,t; 16     bool vis[maxn]; 17     int d[maxn],cur[maxn]; 18     vector<int> G[maxn]; 19     vector<Edge> es; 20      21     void init(int n) { 22         this->n=n; 23         es.clear(); 24         for(int i=0;i<n;i++) G[i].clear(); 25     } 26     void AddEdge(int u,int v,int cap) { 27         es.push_back((Edge){u,v,cap,0}); 28         es.push_back((Edge){v,u,0,0}); 29         m=es.size(); 30         G[u].push_back(m-2); 31         G[v].push_back(m-1); 32     } 33      34     bool BFS() { 35         queue<int> q; 36         memset(vis,0,sizeof(vis)); 37         q.push(s); vis[s]=1; d[s]=0; 38         while(!q.empty()) { 39             int u=q.front(); q.pop(); 40             for(int i=0;i<G[u].size();i++) { 41                 Edge& e=es[G[u][i]]; 42                 int v=e.v; 43                 if(!vis[v] && e.cap>e.flow) { 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 u,int a) { 53         if(u==t || a==0) return a; 54         int flow=0,f; 55         for(int& i=cur[u];i<G[u].size();i++){ 56             Edge& e=es[G[u][i]]; 57             int v=e.v; 58             if( d[v]==d[u]+1 && (f=DFS(v,min(a,e.cap-e.flow)))>0 ) { 59                 e.flow+=f; 60                 es[G[u][i]^1].flow-=f; 61                 flow+=f,a-=f; 62                 if(!a) 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             memset(cur,0,sizeof(cur)); 72             flow+=DFS(s,INF); 73         } 74         return flow; 75     } 76 } dc; 77  78 int n; 79 int w[maxn],d[maxn],a[maxn][maxn]; 80  81 int main() { 82     int T; 83     scanf("%d",&T); 84     while(T--) { 85         scanf("%d",&n); 86         for(int i=0;i<n;i++) scanf("%d%d",&w[i],&d[i]); 87         int sum=0; 88         for(int i=0;i<n;i++) 89             for(int j=0;j<n;j++) scanf("%d",&a[i][j]) , sum+=a[i][j]; 90         sum/=2; 91         int S=n*n+n , T=S+1; 92         bool first=1; 93         for(int team=0;team<n;team++) 94         { 95             int total=w[team]; 96             for(int i=0;i<n;i++) total+=a[team][i]; 97             bool flag=0; 98             for(int i=0;i<n;i++) if(w[i]>total) flag=1;        //即使全胜依然不可能是冠军  99             if(flag) continue;100             dc.init(n*n+n+2);101             for(int i=0;i<n;i++) {102                 for(int j=i+1;j<n;j++) {103                     int r=i*n+j;104                     if(a[i][j]) dc.AddEdge(S,r,a[i][j]);105                     dc.AddEdge(r,n*n+i,INF) , dc.AddEdge(r,n*n+j,INF);106                 }107                 dc.AddEdge(n*n+i,T,total-w[i]);108             }109             if(dc.Maxflow(S,T)==sum) {110                 if(first) first=0; else putchar(' ');111                 printf("%d",team+1);112             }113         }114         putchar('\n');115     }116     return 0;117 }

 

0 0