zoukankan      html  css  js  c++  java
  • 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
    ", ans);
    106     return 0;
    107  }
  • 相关阅读:
    点对点模式1
    简要分析《XXX需求征集系统》采用的可用性和可修改性战术
    淘宝为例进行软件质量属性分析
    浅谈软件架构师的工作
    《软件需求十步走》阅读笔记6
    编写有效的业务用例 读书笔记03
    编写有效的业务用例 读书笔记02
    编写有效的业务用例 读书笔记01
    2017年秋季个人阅读计划
    软件需求与分析需要掌握的内容
  • 原文地址:https://www.cnblogs.com/83131yyl/p/5463420.html
Copyright © 2011-2022 走看看