题目中说每一个good pair<u,v> 都满足(u+v)%2 == 1,即一个奇数,一个偶数。
首先我们要拿出一原点S,汇点T,S联到所有的num[odd]的质因子上,T联到所有的num[even]的质因子上,边的流量为num[i]中相应质因子的个数。
再根据给出的<u,v>,假设u为奇数,则从u的质因子上联到相等的v的质因子上,流量为INF。
丢到模板里跑一遍就好了。
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <queue>
#include <cmath>
#include <stack>
#include <map>
#pragma comment(linker, "/STACK:1024000000");
#define EPS (1e-8)
#define LL long long
#define ULL unsigned long long
#define _LL __int64
#define INF 0x3f3f3f3f
#define Mod 6000007
using namespace std;
const int EDGE = 6000000,POINT = 4010;
struct E
{
int u,v,Max,next;
} edge[EDGE];
int head[POINT];
int curr[POINT];
int Top;
void Link(int u,int v,int flow)
{
//printf("u = %d v = %d flow = %d\n",u,v,flow);
edge[Top].u = u;
edge[Top].v = v;
edge[Top].Max = flow;
edge[Top].next = head[u];
head[u] = Top++;
}
int dis[POINT],gap[POINT],pre[POINT];
queue<int> q;
void Updata_Dis(int S,int T,int n)
{
memset(dis,-1,sizeof(dis));
memset(gap,0,sizeof(gap));
dis[T] = 0;
gap[0] = 1;
q.push(T);
int f;
while(q.empty() == false)
{
f = q.front();
q.pop();
for(int p = head[f]; p != -1; p = edge[p].next)
{
if(dis[edge[p].v] == -1)
{
dis[edge[p].v] = dis[f] + 1;
gap[dis[f]+1]++;
q.push(edge[p].v);
}
}
}
}
int ISAP(int S,int T,int n)
{
memcpy(curr,head,sizeof(curr));
Updata_Dis(S,T,n);
int flow = 0,u = pre[S] = S,p;
while(dis[S] < n)
{
if(u == T)
{
int temp = INF,pos;
for(p = S; p != T; p = edge[curr[p]].v)
{
if(temp > edge[curr[p]].Max)
{
temp = edge[curr[p]].Max;
pos = p;
}
}
for(p = S; p != T; p = edge[curr[p]].v)
{
edge[curr[p]].Max -= temp;
edge[curr[p]^1].Max += temp;
}
flow += temp;
u = pos;
}
for(p = curr[u]; p != -1; p = edge[p].next)
{
if(dis[edge[p].v]+1 == dis[u] && edge[p].Max)
break;
}
if(p != -1)
{
curr[u] = p;
pre[edge[p].v] = u;
u = edge[p].v;
}
else
{
if((--gap[dis[u]]) == 0)
break;
int temp = n;
for(p = head[u]; p != -1; p = edge[p].next)
{
if(temp > dis[edge[p].v] && edge[p].Max)
{
curr[u] = p;
temp = dis[edge[p].v];
}
}
dis[u] = temp+1;
gap[dis[u]]++;
u = pre[u];
}
}
//printf("%d\n",flow);
return flow;
}
bool vis[100010];
int pri[100010];
struct N
{
int d,r;
};
vector<N> vec[110];
int main()
{
int i,j,k,n,m;
memset(vis,false,sizeof(vis));
int ap;
for(i = 2,ap = 0,n = 100000; i <= n; ++i)
{
if(vis[i])
continue;
pri[ap++] = i;
for(j = i+i; j <= n; j += i)
vis[j] = true;
}
scanf("%d %d",&n,&m);
memset(head,-1,sizeof(head));
Top = 0;
int S = 1,T = 4001,ans,x,r = 2;
for(i = 1; i <= n; ++i)
{
scanf("%d",&x);
for(j = 0;j < ap && x >= pri[j]; ++j)
{
ans = 0;
while(x%pri[j] == 0)
{
ans++;
x /= pri[j];
}
if(ans)
{
vec[i].push_back((N){pri[j],r});
if(i&1)
{
Link(S,r,ans);
Link(r,S,0);
}
else
{
Link(r,T,ans);
Link(T,r,0);
}
r++;
}
}
if(x != 1)
{
vec[i].push_back((N){x,r});
if(i&1)
{
Link(S,r,1);
Link(r,S,0);
}
else
{
Link(r,T,1);
Link(T,r,0);
}
r++;
}
}
int u,v;
for(i = 1;i <= m; ++i)
{
scanf("%d %d",&u,&v);
if(v&1)
swap(u,v);
for(j = vec[u].size()-1,k = vec[v].size()-1;j >= 0 && k >= 0; )
{
if(vec[u][j].d == vec[v][k].d)
{
Link(vec[u][j].r,vec[v][k].r,INF);
Link(vec[v][k].r,vec[u][j].r,0);
--j,--k;
}
else if(vec[u][j].d > vec[v][k].d)
{
--j;
}
else
{
--k;
}
}
}
printf("%d\n",ISAP(S,T,T));
return 0;
}
498C - Array and Operations 质因子分解+最大流
原文:http://blog.csdn.net/zmx354/article/details/42805659