山东济南彤昌机械科技有限公司 山东济南江鹏工贸游有限公司

UVa10779 Collectors Problem(最大流)

 

题目链接: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 #include<cstdio>
  2 #include<cstring>
  3 #include<queue>
  4 #include<vector>
  5 using namespace std;
  6 
  7 const int maxn = 100+10;
  8 const int INF = 1e9;
  9 
 10 struct Edge{
 11     int u,v,cap,flow;
 12 };
 13 struct Dinic {
 14     int n,m,s,t;
 15     bool vis[maxn];
 16     int d[maxn],cur[maxn];
 17     vector<int> G[maxn];
 18     vector<Edge> es;
 19     
 20     void init(int n) {
 21         this->n=n;
 22         es.clear();
 23         for(int i=0;i<n;i++) G[i].clear();
 24     }
 25     void AddEdge(int u,int v,int cap) {
 26         es.push_back((Edge){u,v,cap,0});
 27         es.push_back((Edge){v,u,0,0});
 28         m=es.size();
 29         G[u].push_back(m-2);
 30         G[v].push_back(m-1);
 31     }
 32     
 33     bool BFS() {
 34         queue<int> q;
 35         memset(vis,0,sizeof(vis));
 36         q.push(s); vis[s]=1; d[s]=0;
 37         while(!q.empty()) {
 38             int u=q.front(); q.pop();
 39             for(int i=0;i<G[u].size();i++) {
 40                 Edge& e=es[G[u][i]];
 41                 int v=e.v;
 42                 if(!vis[v] && e.cap>e.flow) {
 43                     vis[v]=1;
 44                     d[v]=d[u]+1;
 45                     q.push(v);
 46                 }
 47             }
 48         }
 49         return vis[t];
 50     }
 51     int DFS(int u,int a) {
 52         if(u==t || a==0) return a;
 53         int flow=0,f;
 54         for(int& i=cur[u];i<G[u].size();i++){
 55             Edge& e=es[G[u][i]];
 56             int v=e.v;
 57             if( d[v]==d[u]+1 && (f=DFS(v,min(a,e.cap-e.flow)))>0 ) {
 58                 e.flow+=f;
 59                 es[G[u][i]^1].flow-=f;
 60                 flow+=f,a-=f;
 61                 if(!a) break;
 62             }
 63         }
 64         return flow;
 65     }
 66     int Maxflow(int s,int t) {
 67         this->s=s , this->t=t;
 68         int flow=0;
 69         while(BFS()) {
 70             memset(cur,0,sizeof(cur));
 71             flow+=DFS(s,INF);
 72         }
 73         return flow;
 74     }
 75 }dinic;
 76 
 77 int T,n,m;
 78 int sum[maxn][maxn];
 79 
 80 int main() {
 81     scanf("%d",&T);
 82     int kase=0;
 83     while(T--) {
 84         scanf("%d%d",&n,&m);
 85         dinic.init(n+m+1);
 86         memset(sum,0,sizeof(sum));
 87         int a,b;
 88         for(int i=0;i<n;i++) {
 89             scanf("%d",&a);
 90             for(int j=0;j<a;j++){
 91                 scanf("%d",&b);  
 92                 sum[i][b-1]++;
 93             }
 94         }
 95         int s=n+m-1,t=n+m;
 96         for(int i=0;i<m;i++) {
 97             if(sum[0][i]) dinic.AddEdge(s,i,sum[0][i]);
 98             dinic.AddEdge(i,t,1);
 99         }
100         for(int i=0;i<n;i++)
101             for(int j=0;j<m;j++) {
102                 if(!sum[i][j]) dinic.AddEdge(j,i+m-1,1);
103                 if(sum[i][j]>1) dinic.AddEdge(i+m-1,j,sum[i][j]-1);
104             }
105         printf("Case #%d: %d\n",++kase,dinic.Maxflow(s,t));
106     }
107     return 0;
108 }

 

posted on 2015-12-19 17:13  hahalidaxin  阅读(210)  评论(0编辑  收藏  举报