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

UVAlive2531 The K-League(最大流)

2015-12-20 07:38 519 查看
题目链接: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可行。

【代码】

#include<cstdio>
#include<cstring>
#include<queue>
#include<vector>
#define FOR(a,b,c) for(int a=(b);a<(c);a++)
using namespace std;

const int maxn = 700+10;
const int INF = 1e9;

struct Edge{
int u,v,cap,flow;
};
struct Dinic {
int n,m,s,t;
bool vis[maxn];
int d[maxn],cur[maxn];
vector<int> G[maxn];
vector<Edge> es;

void init(int n) {
this->n=n;
es.clear();
for(int i=0;i<n;i++) G[i].clear();
}
void AddEdge(int u,int v,int cap) {
es.push_back((Edge){u,v,cap,0});
es.push_back((Edge){v,u,0,0});
m=es.size();
G[u].push_back(m-2);
G[v].push_back(m-1);
}

bool BFS() {
queue<int> q;
memset(vis,0,sizeof(vis));
q.push(s); vis[s]=1; d[s]=0;
while(!q.empty()) {
int u=q.front(); q.pop();
for(int i=0;i<G[u].size();i++) {
Edge& e=es[G[u][i]];
int v=e.v;
if(!vis[v] && e.cap>e.flow) {
vis[v]=1;
d[v]=d[u]+1;
q.push(v);
}
}
}
return vis[t];
}
int DFS(int u,int a) {
if(u==t || a==0) return a;
int flow=0,f;
for(int& i=cur[u];i<G[u].size();i++){
Edge& e=es[G[u][i]];
int v=e.v;
if( d[v]==d[u]+1 && (f=DFS(v,min(a,e.cap-e.flow)))>0 ) {
e.flow+=f;
es[G[u][i]^1].flow-=f;
flow+=f,a-=f;
if(!a) break;
}
}
return flow;
}
int Maxflow(int s,int t) {
this->s=s , this->t=t;
int flow=0;
while(BFS()) {
memset(cur,0,sizeof(cur));
flow+=DFS(s,INF);
}
return flow;
}
} dc;

int n;
int w[maxn],d[maxn],a[maxn][maxn];

int main() {
int T;
scanf("%d",&T);
while(T--) {
scanf("%d",&n);
for(int i=0;i<n;i++) scanf("%d%d",&w[i],&d[i]);
int sum=0;
for(int i=0;i<n;i++)
for(int j=0;j<n;j++) scanf("%d",&a[i][j]) , sum+=a[i][j];
sum/=2;
int S=n*n+n , T=S+1;
bool first=1;
for(int team=0;team<n;team++)
{
int total=w[team];
for(int i=0;i<n;i++) total+=a[team][i];
bool flag=0;
for(int i=0;i<n;i++) if(w[i]>total) flag=1;        //即使全胜依然不可能是冠军
if(flag) continue;
dc.init(n*n+n+2);
for(int i=0;i<n;i++) {
for(int j=i+1;j<n;j++) {
int r=i*n+j;
if(a[i][j]) dc.AddEdge(S,r,a[i][j]);
dc.AddEdge(r,n*n+i,INF) , dc.AddEdge(r,n*n+j,INF);
}
dc.AddEdge(n*n+i,T,total-w[i]);
}
if(dc.Maxflow(S,T)==sum) {
if(first) first=0; else putchar(' ');
printf("%d",team+1);
}
}
putchar('\n');
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: