标签:and spl put ios scanf namespace break hid gcc
1.
桌子上现在有m张蓝色卡片和n张红色卡片,每张卡片上有一个大于1的整数。现在你要从桌子上拿走一些卡片,分若干次拿。每次只能拿走一组卡片:这组卡片颜色不同,并且两张卡片上面的数字的最大公约数大于1。问:最多可以从桌上拿走多少张卡片。
直接建图应该是可以的,但是出题人特意卡了直接建图的,我们需要考虑怎么减少建图的边数。考虑 “最大公约数大于1” 这个条件,我们可以把他们的质因子筛出来,因为所有数的质因子个数比较小,**我们可以向质因子连边**,以质因子为中转站。这样连边条数为 n*( 质因子数量 + 1 ) + m * ( 质因子数量 + 1 )
1 //#pragma GCC optimize(2) 2 #include<cstdio> 3 #include<iostream> 4 #include<string> 5 #include<cstring> 6 #include<map> 7 #include<cmath> 8 #include<cctype> 9 #include<vector> 10 #include<set> 11 #include<queue> 12 #include<algorithm> 13 #include<sstream> 14 #include<ctime> 15 #include<cstdlib> 16 #define X first 17 #define Y second 18 #define L (u<<1) 19 #define R (u<<1|1) 20 #define pb push_back 21 #define mk make_pair 22 #define Mid (tr[u].l+tr[u].r>>1) 23 #define Len(u) (tr[u].r-tr[u].l+1) 24 #define random(a,b) ((a)+rand()%((b)-(a)+1)) 25 #define db puts("---") 26 using namespace std; 27 28 void rd_cre() { freopen("d://dp//data.txt","w",stdout); srand(time(NULL)); } 29 void rd_ac() { freopen("d://dp//data.txt","r",stdin); freopen("d://dp//AC.txt","w",stdout); } 30 void rd_wa() { freopen("d://dp//data.txt","r",stdin); freopen("d://dp//WA.txt","w",stdout); } 31 32 typedef long long LL; 33 typedef unsigned long long ULL; 34 typedef pair<int,int> PII; 35 36 const int N=10010,M=N*N,mod=1e9+7,INF=0x3f3f3f3f; 37 const double eps=1e-6; 38 39 int n,m,S,T; 40 int a[N],b[N]; 41 int e[M],ne[M],w[M],h[N],hs[N],idx; 42 int depth[N],tot; 43 map<int,int>mp; 44 45 void add(int a,int b,int c) 46 { 47 e[idx]=b,w[idx]=c,ne[idx]=h[a],h[a]=idx++; 48 e[idx]=a,w[idx]=0,ne[idx]=h[b],h[b]=idx++; 49 } 50 51 bool bfs() 52 { 53 queue<int>q; q.push(S); 54 memset(depth,-1,sizeof (depth)); 55 depth[S]=0; hs[S]=h[S]; 56 while(q.size()) 57 { 58 int u=q.front(); q.pop(); 59 for(int i=h[u];~i;i=ne[i]) 60 { 61 int ver=e[i]; 62 if(depth[ver]==-1&&w[i]) 63 { 64 depth[ver]=depth[u]+1; 65 hs[ver]=h[ver]; 66 if(ver==T) return true; 67 q.push(ver); 68 } 69 } 70 } 71 return false; 72 } 73 74 int dfs(int u,int flow) 75 { 76 if(u==T) return flow; 77 int d=flow; 78 for(int i=hs[u];~i;i=ne[i]) 79 { 80 hs[u]=i; int ver=e[i]; 81 if(depth[ver]==depth[u]+1&&w[i]) 82 { 83 int v=dfs(ver,min(w[i],d)); 84 if(!v) depth[ver]=-1; 85 d-=v; w[i]-=v; w[i^1]+=v; 86 if(!d) break; 87 } 88 } 89 return flow-d; 90 } 91 92 int dinic() 93 { 94 int ans=0,flow; 95 while(bfs()) while(flow=dfs(S,INF)) ans+=flow; 96 return ans; 97 } 98 99 int get(int x) 100 { 101 if(!mp.count(x)) return mp[x]=++tot; 102 else return mp[x]; 103 } 104 105 void divide(int x,int id,int flow) 106 { 107 for(int i=2;i<=x/i;i++) 108 if(x%i==0) 109 { 110 if(flow==1) add(id,get(i),flow); 111 else add(get(i),id,flow); 112 while(x%i==0) x/=i; 113 } 114 if(x>1) 115 { 116 if(flow==1) add(id,get(x),flow); 117 else add(get(x),id,flow); 118 } 119 } 120 121 int main() 122 { 123 // ios::sync_with_stdio(false); 124 // cin.tie(0); 125 126 int _; 127 while(scanf("%d",&_)!=EOF) 128 { 129 while(_--) 130 { 131 scanf("%d%d",&n,&m); tot=n+m+1; mp.clear(); 132 memset(h,-1,sizeof(h)); 133 idx=0; S=0,T=n+m+1; 134 for(int i=1;i<=n;i++) 135 { 136 scanf("%d",&a[i]); 137 divide(a[i],i,1); 138 } 139 for(int i=1;i<=m;i++) 140 { 141 scanf("%d",&b[i]); 142 divide(b[i],i+n,INF); 143 } 144 for(int i=1;i<=n;i++) add(S,i,1); 145 for(int i=1;i<=m;i++) add(i+n,T,1); 146 printf("%d\n",dinic()); 147 } 148 } 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 return 0; 169 } 170 /* 171 172 */
标签:and spl put ios scanf namespace break hid gcc
原文地址:https://www.cnblogs.com/LibraGlow/p/14022781.html