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可行。
【代码】
【思路】
最大流。
大体思路是枚举每个队伍,最大流判断是否可能成为冠军。
构图:
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; }
相关文章推荐
- UI交互设计的网站
- 动态修改UINavigationBar的背景色
- Leetcode: Implement Queue using Stacks
- IPtables中SNAT和MASQUERADE的区别
- QuickContactBadge 自定义获取联系人
- ERROR: No query specified
- UILabel,UIButton,UITextField的简单使用
- UIUITableView 分组标题
- UIView中的坐标转换
- 改变UITableView的headerView、footerView背景颜色
- Android布局问题: No resource found that matches the given name (at 'layout_above' with value @id/tv)
- UESTC 653 扫雷 模拟
- UIScrollView自动布局
- DSOJ Level-order sequence with degree(森林的带度数层次遍历序列)
- 给UILable中的文字添加删除线样式
- Request和Response详解
- iOS开发中UIPopoverController的使用详解
- Django中Request 对象介绍
- UIAlertController 和 UIAlertView的使用
- UVA 1594 set 里面放queue