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 }