POJ2289-Jamie's Contact Groups-二分图多重匹配-ISAP
注意POJ数组越界可能返回TLE!!!
网络流的maxn大小要注意
其他没什么了 裸二分答案+isap乱搞
不过复杂度没搞懂 V=1e3 E = 1e5 那ISAP的O(V^2E)怎么算都不行啊
1 /*--------------------------------------------------------------------------------------*/ 2 3 #include <algorithm> 4 #include <iostream> 5 #include <cstring> 6 #include <ctype.h> 7 #include <cstdlib> 8 #include <cstdio> 9 #include <vector> 10 #include <string> 11 #include <queue> 12 #include <stack> 13 #include <cmath> 14 #include <set> 15 #include <map> 16 17 //debug function for a N*M array 18 #define debug_map(N,M,G) printf("\n");for(int i=0;i<(N);i++)\ 19 {for(int j=0;j<(M);j++){\ 20 printf("%d",G[i][j]);}printf("\n");} 21 //debug function for int,float,double,etc. 22 #define debug_var(X) cout<<#X"="<<X<<endl; 23 #define LL long long 24 const int INF = 0x3f3f3f3f; 25 const LL LLINF = 0x3f3f3f3f3f3f3f3f; 26 /*--------------------------------------------------------------------------------------*/ 27 using namespace std; 28 29 int N,M,T; 30 const int maxn = 2010; 31 const int maxm = 2000010; 32 //map<int ,string > mp; 33 vector <int> save[maxn]; 34 35 struct Edge{ 36 int to,next,cap,flow; 37 }edge[maxm]; 38 39 int head[maxn],tot; 40 int uN = 0; 41 int gap[maxn],dep[maxn],pre[maxn],cur[maxn]; 42 43 void init() 44 { 45 tot = 0; 46 memset(head,-1,sizeof head); 47 } 48 49 void add_edge(int u,int v,int w,int rw = 0) 50 { 51 //printf("%d->%d %d\n",u,v,w); 52 edge[tot].to = v;edge[tot].cap = w;edge[tot].next = head[u]; 53 edge[tot].flow = 0;head[u] = tot++; 54 edge[tot].to = u;edge[tot].cap = rw;edge[tot].next = head[v]; 55 edge[tot].flow = 0;head[v] = tot++; 56 } 57 int Q[maxn]; 58 void BFS(int st,int ed) 59 { 60 memset(dep,-1,sizeof dep); 61 memset(gap,0,sizeof gap); 62 gap[0] = 1; 63 int front = 0,rear = 0; 64 dep[ed] = 0; 65 Q[rear++] = ed; 66 while(front != rear) 67 { 68 int u = Q[front++]; 69 for(int i=head[u];~i;i=edge[i].next) 70 { 71 int v = edge[i].to; 72 if(dep[v] != -1) continue; 73 Q[rear++] = v; 74 dep[v] = dep[u] + 1; 75 gap[dep[v]] ++; 76 } 77 } 78 } 79 int S[maxn]; 80 81 int sap(int st,int ed) 82 { 83 BFS(st,ed); 84 memcpy(cur,head,sizeof head); 85 int top = 0; 86 int u = st; 87 88 int ans = 0; 89 while(dep[st] < uN) 90 { 91 if(u == ed) 92 { 93 int Min = INF; 94 int inser; 95 for(int i=0;i<top;i++) 96 { 97 if(Min > edge[S[i]].cap - edge[S[i] ].flow) 98 { 99 Min = edge[S[i]].cap - edge[S[i]].flow; 100 inser=i; 101 } 102 } 103 for(int i=0;i<top;i++) 104 { 105 edge[S[i]].flow += Min; 106 edge[S[i]^1].flow -= Min; 107 } 108 ans += Min; 109 top = inser; 110 u = edge[S[top]^1].to; 111 continue; 112 } 113 bool flag = false; 114 int v; 115 for(int i=cur[u];~i;i=edge[i].next) 116 { 117 v = edge[i].to; 118 if(edge[i].cap - edge[i].flow && dep[v]+1 == dep[u]) 119 { 120 flag = true; 121 cur[u] = i; 122 break; 123 } 124 } 125 if(flag) 126 { 127 S[top++] = cur[u]; 128 u = v; 129 continue; 130 } 131 int Min = uN; 132 for(int i=head[u];~i;i=edge[i].next) 133 { 134 if(edge[i].cap - edge[i].flow && dep[edge[i].to] < Min) 135 { 136 Min = dep[edge[i].to]; 137 cur[u] = i; 138 } 139 } 140 gap[dep[u]] --; 141 if(!gap[dep[u]]) return ans; 142 dep[u] = Min + 1; 143 gap[dep[u] ]++; 144 if(u != st) u = edge[S[--top]^1].to; 145 } 146 return ans; 147 } 148 149 int check(int mid) 150 { 151 uN = N+M+2; 152 init(); 153 for(int i=0;i<N;i++) 154 { 155 add_edge(N+M,i,1); 156 for(int j=0;j<save[i].size();j++) 157 { 158 add_edge(i,save[i][j]+N,1); 159 } 160 } 161 for(int i=0;i<M;i++) 162 { 163 add_edge(N+i,N+M+1,mid); 164 } 165 166 int res = sap(N+M,N+M+1); 167 //printf("mid:%d res:%d\n",mid,res); 168 if(res == N) return true; 169 else return false; 170 } 171 172 int solve() 173 { 174 int L = 0,R = 2*N,mid; 175 while(L <= R) 176 { 177 mid = (L+R)>>1; 178 if(check(mid)) R = mid-1; 179 else L = mid+1; 180 } 181 //printf("%d %d\n",L,R); 182 return L; 183 } 184 185 int main() 186 { 187 while(scanf("%d%d",&N,&M) && N+M) 188 { 189 char s[20]; 190 //mp.clear(); 191 for(int i=0;i<maxn;i++) save[i].clear(); 192 for(int i=0;i<N;i++) 193 { 194 scanf("%s",s); 195 char c = getchar(); 196 if(c != ' ') continue; 197 int num = -1; 198 while((c = getchar()) && c !='\n') 199 { 200 if(isdigit(c)) 201 { 202 if(num == -1) num = 0; 203 num *= 10;num += c-'0'; 204 } 205 else if(c == ' ') 206 { 207 save[i].push_back(num); 208 num = -1; 209 } 210 } 211 if(num != -1) save[i].push_back(num); 212 } 213 if(M == 0 || N == 0) printf("0\n"); 214 else printf("%d\n",solve()); 215 } 216 }