您的位置:首页 > 产品设计 > UI/UE

UVAlive2531 The K-League(最大流)

2016-03-30 17:32 471 查看
题目链接: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 }
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: