1. 程式人生 > >uva 10779 Collectors Problem

uva 10779 Collectors Problem

add -1 inf stdin 輸入 stream 交換 共有m個 val

題目描述:

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

uva 10779 Collectors Problem