这题题意给你N个数,用a1...aN 表示,还有M个组合。每个组合 有 (ai,aj),保证了 i+j 为奇数
然后现在有个操作, 找任意一个组合 里面 ai,aj 的公约数用V表示 然后 ai= ai/v ,aj=aj/v
问这样的操作最多有多少次。
首先想到最多次数,那么每次找质因子为公约数这样可以保证次数最多
然后想到网络流来求最大次数,但是却不知道图怎么去建使得不会让同一个点算多次
最后想到枚举质因子 ,然后起点 连 奇数点,流量为这个数含有 枚举的质因子的个数
偶数点连汇点,流量为这个数含有 枚举的质因子的个数,每个组合按照奇数连偶数点,流量为无穷
每次枚举质因子就重建一次图。。
代码如下
#include<iostream>
#include<algorithm>
#include<stdio.h>
#include<string.h>
#include<queue>
using namespace std;
#define INFF 0x3fffffff
struct node
{
int en,flow;
int next;
}E[10010];
int p[1100],num;
void init()
{
memset(p,-1,sizeof(p));
num=0;
}
void add(int st,int en,int flow)
{
E[num].en=en;
E[num].flow=flow;
E[num].next=p[st];
p[st]=num++;
E[num].en=st;
E[num].flow=0;
E[num].next=p[en];
p[en]=num++;
}
int d[1100];
int cur[1100];
bool vis[1100];
bool bfs(int st,int en)
{
memset(vis,false,sizeof(vis));
d[st]=0;
vis[st]=true;
queue<int>q;
q.push(st);
while(!q.empty())
{
int u=q.front();
q.pop();
for(int i=p[u];i+1;i=E[i].next)
{
int v=E[i].en;
if(!vis[v]&&E[i].flow)
{
vis[v]=true;
d[v]=d[u]+1;
q.push(v);
}
}
}
return vis[en];
}
int dfs(int st,int en,int flow)
{
if(st==en || flow==0)
return flow;
int f=0,dd;
for(int &i=cur[st];i+1;i=E[i].next)
{
int v=E[i].en;
if(d[st]+1==d[v] && (dd=dfs(v,en,min(flow,E[i].flow)))>0)
{
E[i].flow-=dd;
E[i^1].flow+=dd;
flow-=dd;
f+=dd;
if(flow==0)
break;
}
}
return f;
}
int dinic(int st,int en,int n)
{
int flow=0;
while(bfs(st,en))
{
for(int i=0;i<=n;i++)
cur[i]=p[i];
flow+=dfs(st,en,INFF);
}
return flow;
}
vector<int>zhi[110];
int meiju[5000],ge;
int fun(int x,int id)
{
for(int i=2;i*i<=x;i++)
{
if(x%i==0)
{
meiju[ge++]=i;
while(x%i==0)
{ zhi[id].push_back(i);
x/=i;
}
}
}
if(x>1)
{
zhi[id].push_back(x);
meiju[ge++]=x;
}
}
int a[110];
int x[110],y[110];
int main()
{
int n,m;
while(scanf("%d %d",&n,&m)!=EOF)
{
ge=0;
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
fun(a[i],i);
}
for(int i=1;i<=m;i++)
{
scanf("%d %d",&x[i],&y[i]);
if(x[i]%2==0)
swap(x[i],y[i]);
}
sort(meiju,meiju+ge);
int cnt=unique(meiju,meiju+ge)-meiju;
int ans=0,tt=n+1;
for(int i=0;i<cnt;i++)
{
init();
for(int j=1;j<=n;j++)
{
int c=0;
for(int k=0;k<zhi[j].size();k++)
{
if(zhi[j][k]==meiju[i])
c++;
}
if(j%2==1)
add(0,j,c);
else
add(j,tt,c);
}
for(int j=1;j<=m;j++)
{
add(x[j],y[j],INFF);
}
int temp=dinic(0,tt,tt);
ans+=temp;
}
printf("%d\n",ans);
}
return 0;
}