码迷,mamicode.com
首页 > 其他好文 > 详细

网络流建图总结

时间:2020-11-26 14:51:15      阅读:4      评论:0      收藏:0      [点我收藏+]

标签:and   spl   put   ios   scanf   namespace   break   hid   gcc   

1.

P2065 [TJOI2011]卡片

桌子上现在有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 */
View Code

 

网络流建图总结

标签:and   spl   put   ios   scanf   namespace   break   hid   gcc   

原文地址:https://www.cnblogs.com/LibraGlow/p/14022781.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!