uva 10779 Collectors Problem

题目描述:

Bob和他的朋友从糖果包装里收集贴纸。Bob和他的朋友总共n人。共有m种不同的贴纸。
每人手里都有一些(可能有重复的)贴纸,并且只跟别人交换他所没有的贴纸。贴纸总是一对一交换。
Bob比这些朋友更聪明,因为他意识到只跟别人交换自己没有的贴纸并不总是最优的。在某些情况下,换来一张重复的贴纸更划算。
假设Bob的朋友只跟Bob交换(他们之间不交换),并且这些朋友只会出让手里的重复贴纸来交换他们没有的不同贴纸。你的任务是帮助Bob算出他最终可以得到的不同贴纸的最大数量。
2 ≤ n ≤ 10, 5 ≤ m ≤ 25

solution:

网络流最大流

把每一个糖纸建成一个节点,一共有m个

除了bob的n-1个人(我们定义他们叫sbzyf)建成n-1个节点

对于第i种糖纸,如果sbzyf有v个

有1个:则不连边

有0个:则他可以接受1个,就把第i个糖纸的节点向他连一条 1 的边

有v>1个:则他可以给v-1个,就把他向第i个糖纸连 v-1 的边

(ps:再输入的时候  把j打成了i  调了半个小时.....)

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<iostream>
  4 #define mem(a,b) memset(a,b,sizeof(a))
  5 using namespace std;
  6 const int INF=(1<<31)-1;
  7 inline int minn(int a,int b){return a<b?a:b;}
  8 struct son
  9 {
 10     int v,next,w,u;
 11 };
 12 son a1[50001];
 13 int first[50001],e;
 14 
 15 void addbian(int u,int v,int w)
 16 {
 17     a1[e].u=u;
 18     a1[e].v=v;
 19     a1[e].w=w;
 20     a1[e].next=first[u];
 21     first[u]=e++;
 22 }
 23 
 24 int t,n,m;
 25 int u,o,p;
 26 int S,T;
 27 int ji[27];
 28 int dep[201];
 29 
 30 int dui[1000001],he,en;
 31 inline void clear(){he=1;en=0;}
 32 inline void push(int x){dui[++en]=x;}
 33 inline int top(){return dui[he];}
 34 inline void pop(){++he;}
 35 inline bool empty(){return en>=he?0:1;}
 36 
 37 int bfs()
 38 {
 39     mem(dep,0);
 40     clear();
 41     dep[S]=1;push(S);
 42     while(!empty())
 43     {
 44         int now=top();pop();
 45         //printf("now=%d\n",now);
 46         for(int i=first[now];i!=-1;i=a1[i].next)
 47         {
 48             int temp=a1[i].v;
 49             if(dep[temp]||!a1[i].w)continue;
 50             dep[temp]=dep[now]+1;
 51             push(temp);
 52             if(temp==T)return 1;
 53         }
 54     }
 55     return 0;
 56 }
 57 
 58 int dfs(int x,int val)
 59 {
 60     //printf("x=%d\n",x);
 61     if(x==T)return val;
 62     int val2=val,k;
 63     for(int i=first[x];i!=-1;i=a1[i].next)
 64     {
 65         int temp=a1[i].v;
 66         if(dep[temp]!=dep[x]+1||!a1[i].w||!val2)continue;
 67         k=dfs(temp,minn(val2,a1[i].w));
 68         if(!k){dep[temp]=0;continue;}
 69         a1[i].w-=k;a1[i^1].w+=k;val2-=k;
 70     }
 71     return val-val2;
 72 }
 73 
 74 int Dinic()
 75 {
 76     int ans=0;
 77     while(bfs())
 78       ans+=dfs(S,INF);
 79     return ans;
 80 }
 81 
 82 void chu()
 83 {
 84     mem(a1,0);
 85     mem(first,-1);
 86     e=0;
 87 }
 88 
 89 void out11()
 90 {
 91     printf("\n");
 92     for(int i=S;i<=T;++i)
 93     {
 94         printf("i=%d\n",i);
 95         for(int j=first[i];j!=-1;j=a1[j].next)
 96           printf("%d ",a1[j].v);
 97         printf("\n");
 98     }
 99     printf("\n");
100 }
101 
102 int main(){
103     //freopen("1.txt","r",stdin);
104     scanf("%d",&t);
105     for(int l=1;l<=t;++l)
106     {
107         chu();
108         scanf("%d%d",&n,&m);
109         S=0;T=n+m;
110         
111         mem(ji,0);
112         scanf("%d",&u);
113         for(int i=1;i<=u;++i){scanf("%d",&o);++ji[o];}
114         for(int i=1;i<=m;++i)
115             if(ji[i])
116             {
117                 addbian(S,i,ji[i]);
118                 addbian(i,S,0);
119             }
120         
121         for(int i=1;i<n;++i)
122         {
123             mem(ji,0);
124             scanf("%d",&u);
125             for(int j=1;j<=u;++j)
126             {
127                 scanf("%d",&o);
128                 ++ji[o];
129             }
130             
131             /*printf("\n");
132             printf("i=%d\n",i);
133             for(int j=1;j<=m;++j)
134               printf("%d ",ji[j]);
135             printf("\n");*/
136             
137             for(int j=1;j<=m;++j)
138             {
139                 if(!ji[j])
140                 {
141                     addbian(j,i+m,1);
142                     addbian(i+m,j,0);
143                 }
144                 else
145                   if(ji[j]>1)
146                   {
147                         addbian(i+m,j,ji[j]-1);
148                         addbian(j,i+m,0);
149                     }
150             }
151         }
152         
153         for(int i=1;i<=m;++i)
154         {
155             addbian(i,T,1);
156             addbian(T,i,0);
157         }
158         
159         //out11();
160         
161         //cout<<0;
162         printf("Case #%d: %d\n",l,Dinic());
163         //cout<<1;
164     }
165     //while(1);
166     return 0;
167 }
code

转载于:https://www.cnblogs.com/A-LEAF/p/7256933.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值