4205: 卡牌配对 最大流+建图技巧
很明显该题应该是二分图最大匹配,但该题不可能N^2建图,那么我们要怎么办呢?而且有三个属性。 注意到 Ai <= 200 而且 200 以内的质数只有49个,那么我们就可以对着仅有的49个质数下毒手了。很明显如果 Ai 与 Aj 不互质的话, 两者应该有一个共同质因子。 B和C同理。 那么我们可以在S集和T集中间建3层质因子的墙,分别为A和B, B和C, C和A。 只有当 Ai 被第 x 个质因子整除, Bi 被第 y 个质因子整除时, 我们从 i 往 P[0][x][y] 连边。 其他同理。 这样的话每个点连出的边数不超过30. 可以跑了。
1 #include<cstdio> 2 #include<iostream> 3 #define rep(i,j,k) for(register int i = j; i <= k; i++) 4 #define ez(i,j) for(register int i = head[j]; i; i=e[i].next) 5 #define maxn 30005 6 #define maxm 70233 7 #define inf 0x7fffffff 8 using namespace std; 9 10 inline int read() { 11 int s = 0, t = 1; char c = getchar(); 12 while( !isdigit(c) ) { if( c == '-' ) t = -1; c = getchar(); } 13 while( isdigit(c) ) s = s * 10 + c - 48, c = getchar(); 14 return s * t; 15 } 16 17 struct edge{ int to, v, next; } e[maxm*500]; 18 int head[maxm], S = 0, T, cnt = 1; 19 inline void add(int x,int y,int v) { 20 e[++cnt].to = y, e[cnt].v = v, e[cnt].next = head[x], head[x] = cnt; 21 e[++cnt].to = x, e[cnt].v = 0, e[cnt].next = head[y], head[y] = cnt; 22 } 23 24 int l, r, h[maxm], q[maxm]; 25 #define to e[i].to 26 inline bool bfs() { 27 rep(i,1,T) h[i] = 0; h[S] = 1; 28 l = 0, r = 1; q[r] = S; int x; 29 while( l < r ) { 30 x = q[++l]; 31 ez(i,x) if( !h[to] && e[i].v ) h[to] = h[x] + 1, q[++r] = to; 32 } 33 return h[T]; 34 } 35 36 inline int dfs(int x,int f) { 37 if( x == T ) return f; 38 int used = 0, w; 39 ez(i,x) if( h[to] == h[x] + 1 && e[i].v ) { 40 w = dfs(to,min(e[i].v,f-used)); 41 e[i].v -= w, e[i^1].v += w; used += w; 42 if( used == f ) return f; 43 } 44 if( !used ) h[x] = -1; 45 return used; 46 } 47 48 int A[maxn], B[maxn], C[maxn], n, m, ans = 0; 49 int pri[] = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199}; 50 int bet[3][49][49], inl[maxn], inr[maxn], aq[maxn], bq[maxn], cq[maxn]; 51 52 inline void flow() { while( bfs() ) ans += dfs(S,inf); } 53 int main() { 54 int n = read(), m = read(), l1, l2, l3, x, tot = 0; 55 rep(i,0,2) rep(j,0,48) rep(k,0,48) bet[i][j][k] = ++tot; 56 rep(i,1,n) inl[i] = ++tot; rep(i,1,m) inr[i] = ++tot; 57 S = 0, T = ++tot; 58 rep(i,1,n) A[i] = read(), B[i] = read(), C[i] = read(); 59 rep(k,1,n) { 60 add(S,inl[k],1); 61 l1 = 0, l2 = 0, l3 = 0; 62 x = A[k]; 63 rep(i,0,48) if( x % pri[i] == 0 ) { 64 aq[++l1] = i; 65 while( x % pri[i] == 0 ) x /= pri[i]; 66 } else if( x == 1 ) break; 67 x = B[k]; 68 rep(i,0,48) if( x % pri[i] == 0 ) { 69 bq[++l2] = i; 70 while( x % pri[i] == 0 ) x /= pri[i]; 71 } else if( x == 1 ) break; 72 x = C[k]; 73 rep(i,0,48) if( x % pri[i] == 0 ) { 74 cq[++l3] = i; 75 while( x % pri[i] == 0 ) x /= pri[i]; 76 } else if( x == 1 ) break; 77 rep(i,1,l1) rep(j,1,l2) add(inl[k],bet[0][aq[i]][bq[j]],1); 78 rep(i,1,l2) rep(j,1,l3) add(inl[k],bet[1][bq[i]][cq[j]],1); 79 rep(i,1,l3) rep(j,1,l1) add(inl[k],bet[2][cq[i]][aq[j]],1); 80 } 81 rep(i,1,m) A[i] = read(), B[i] = read(), C[i] = read(); 82 rep(k,1,m) { 83 add(inr[k],T,1); 84 l1 = 0, l2 = 0, l3 = 0; 85 x = A[k]; 86 rep(i,0,48) if( x % pri[i] == 0 ) { 87 aq[++l1] = i; 88 while( x % pri[i] == 0 ) x /= pri[i]; 89 } else if( x == 1 ) break; 90 x = B[k]; 91 rep(i,0,48) if( x % pri[i] == 0 ) { 92 bq[++l2] = i; 93 while( x % pri[i] == 0 ) x /= pri[i]; 94 } else if( x == 1 ) break; 95 x = C[k]; 96 rep(i,0,48) if( x % pri[i] == 0 ) { 97 cq[++l3] = i; 98 while( x % pri[i] == 0 ) x /= pri[i]; 99 } else if( x == 1 ) break; 100 rep(i,1,l1) rep(j,1,l2) add(bet[0][aq[i]][bq[j]],inr[k],1); 101 rep(i,1,l2) rep(j,1,l3) add(bet[1][bq[i]][cq[j]],inr[k],1); 102 rep(i,1,l3) rep(j,1,l1) add(bet[2][cq[i]][aq[j]],inr[k],1); 103 } 104 flow(); 105 printf("%d\n", ans); 106 return 0; 107 }
————————————————