zoukankan      html  css  js  c++  java
  • UVAlive2531 The K-League(最大流)

    题目链接: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('
    ');
    115     }
    116     return 0;
    117 }
  • 相关阅读:
    Android存储数据方式(转)
    Android实现双进程守护 (转)
    Android DOM、SAX、Pull解析XML(转)
    TCP/IP和Socket的关系(转)
    Socket通信原理和实践
    [转]Android中Intent传递对象的两种方法(Serializable,Parcelable)
    内存堆和栈的区别
    hdu 1754 线段树
    hdu 1166 线段树
    zoj 3686 线段树
  • 原文地址:https://www.cnblogs.com/lidaxin/p/5060230.html
Copyright © 2011-2022 走看看