UVa10779 Collectors Problem(最大流)
2015-12-19 17:13
218 查看
题目链接:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=33631
【思路】
最大流。
构图:
1 建立m个x点表示贴纸,n-1个y点表示Bob的朋友,ST表示源汇点。
2 S向x[j]连一条容量为sum[0][j]的边,表示Bob可以换出如是贴纸。
3 y[j]向x[i]连容量为1的边当且仅当i没有j,x[i]向y[j]连容量为sum[i][j]-1的边。
4 x[i]向T连一条容量为1的边统计不同种类的数目。
【代码】
【思路】
最大流。
构图:
1 建立m个x点表示贴纸,n-1个y点表示Bob的朋友,ST表示源汇点。
2 S向x[j]连一条容量为sum[0][j]的边,表示Bob可以换出如是贴纸。
3 y[j]向x[i]连容量为1的边当且仅当i没有j,x[i]向y[j]连容量为sum[i][j]-1的边。
4 x[i]向T连一条容量为1的边统计不同种类的数目。
【代码】
#include<cstdio> #include<cstring> #include<queue> #include<vector> using namespace std; const int maxn = 100+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; } }dinic; int T,n,m; int sum[maxn][maxn]; int main() { scanf("%d",&T); int kase=0; while(T--) { scanf("%d%d",&n,&m); dinic.init(n+m+1); memset(sum,0,sizeof(sum)); int a,b; for(int i=0;i<n;i++) { scanf("%d",&a); for(int j=0;j<a;j++){ scanf("%d",&b); sum[i][b-1]++; } } int s=n+m-1,t=n+m; for(int i=0;i<m;i++) { if(sum[0][i]) dinic.AddEdge(s,i,sum[0][i]); dinic.AddEdge(i,t,1); } for(int i=0;i<n;i++) for(int j=0;j<m;j++) { if(!sum[i][j]) dinic.AddEdge(j,i+m-1,1); if(sum[i][j]>1) dinic.AddEdge(i+m-1,j,sum[i][j]-1); } printf("Case #%d: %d\n",++kase,dinic.Maxflow(s,t)); } return 0; }
相关文章推荐
- maven核心,pom.xml详解
- 安装jpeg-6b时出现的错误
- 使用Matplotlib绘制正余弦函数、抛物线
- 给树莓派安装vnc server并设置自启动
- 字符串的基本概念
- java抓取网页数据获取网页中所有的链接实例分享
- iOS 数据库离线缓存思路和网络层封装
- Basic Calculator
- android核心组件Activity的跳转
- 【转载】MySQL开发规范
- OC学习之文件目录操作
- python的按位运算
- SaberRD之蒙特卡罗分析(一)
- 如何在Flash(as3.0)文件中添加SCORM标准?
- MySQL数据库相关命令
- PAT乙级 反转链表 (25)
- springMVC整合spring和hibernate4(适合于框架的搭建)
- 崩溃问题:iOS9 This application is modifying the autolayout engine from a background thread, which
- Android性能优化——Layout的优化
- ubuntu14.04 开机自动运行应用程序