现在的位置: 首页 > 综合 > 正文

Codeforces 489C. Array and Operations Hopcroft-Karp

2017年10月18日 ⁄ 综合 ⁄ 共 3410字 ⁄ 字号 评论关闭

将每一个数分解质因数,暴力连边后二分图匹配,

但是匈牙利肯定得超时,所以我们的选择是 Hopcroft-Karp

 Hopcroft-Karp ( sqrt(V)*E)  很高效的二分图匹配算法

C. Array and Operations
time limit per test

1 second

memory limit per test

256 megabytes

input

standard input

output

standard output

You have written on a piece of paper an array of n positive integers a[1], a[2], ..., a[n] and m good pairs
of integers (i1, j1), (i2, j2), ..., (im, jm).
Each good pair (ik, jk) meets
the following conditions: ik + jk is
an odd number and 1 ≤ ik < jk ≤ n.

In one operation you can perform a sequence of actions:

  • take one of the good pairs (ik, jk) and
    some integer v (v > 1), which divides both numbers a[ik] and a[jk];
  • divide both numbers by v, i. e. perform the assignments:  and .

Determine the maximum number of operations you can sequentially perform on the given array. Note that one pair may be used several times in the described operations.

Input

The first line contains two space-separated integers nm (2 ≤ n ≤ 1001 ≤ m ≤ 100).

The second line contains n space-separated integers a[1], a[2], ..., a[n] (1 ≤ a[i] ≤ 109)
— the description of the array.

The following m lines contain the description of good pairs. The k-th
line contains two space-separated integers ikjk (1 ≤ ik < jk ≤ nik + jk is
an odd number).

It is guaranteed that all the good pairs are distinct.

Output

Output the answer for the problem.

Sample test(s)
input
3 2
8 3 8
1 2
2 3
output
0
input
3 2
8 12 8
1 2
2 3
output
2


/* ***********************************************
Author        :CKboss
Created Time  :2014年12月27日 星期六 20时33分02秒
File Name     :CF498C_2.cpp
************************************************ */

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <string>
#include <cmath>
#include <cstdlib>
#include <vector>
#include <queue>
#include <set>
#include <map>

using namespace std;

const int INF=0x3f3f3f3f;
const int maxn=5500;

int n,m;
int a[111];

int nt;
int A2[5500]; /// Pr;

bool vis[111];

struct Point
{
	int from,to;
}pt[111];

void fenjie(int id,int x)
{
	/// fenjie prime
	int R=-INF,L=INF;

	for(int i=2;i*i<=x;i++)
	{
		while(x%i==0)
		{
			R=max(R,nt); L=min(L,nt);
			A2[nt++]=i;
			x/=i;
		}
	}
	if(x!=1)
	{
		R=max(R,nt); L=min(L,nt);
		A2[nt++]=x;
	}
	pt[id].from=L; pt[id].to=R;
}

/**********************************/
/// Hopcroft-Karp

int Mx[maxn],My[maxn];
int dx[maxn],dy[maxn];
int dis;
bool used[maxn];
int uN;
vector<int> G[maxn];

bool SearchP()
{
	queue<int> Q;
	dis = INF;
	memset(dx,-1,sizeof(dx));
	memset(dy,-1,sizeof(dy));
	for(int i=0;i<uN;i++)
	{
		if(Mx[i]==-1)
		{
			Q.push(i);
			dx[i]=0;
		}
	}
	while(!Q.empty())
	{
		int u = Q.front();
		Q.pop();
		if(dx[u]>dis) break;
		int sz = G[u].size();
		for(int i=0;i<sz;i++)
		{
			int v = G[u][i];
			if(dy[v]==-1)
			{
				dy[v]=dx[u]+1;
				if(My[v]==-1) dis = dy[v];
				else
				{
					dx[My[v]]=dy[v]+1;
					Q.push(My[v]);
				}
			}
		}
	}
	return dis!=INF;
}

bool DFS(int u)
{
	int sz=G[u].size();
	for(int i=0;i<sz;i++)
	{
		int v=G[u][i];
		if(!used[v]&&dy[v]==dx[u]+1)
		{
			used[v]=true;
			if(My[v]!=-1&&dy[v]==dis) continue;
			if(My[v]==-1||DFS(My[v]))
			{
				My[v]=u;
				Mx[u]=v;
				return true;
			}
		}
	}
	return false;
}

int MaxMatch()
{
	int res=0;
	memset(Mx,-1,sizeof(Mx));
	memset(My,-1,sizeof(My));
	while(SearchP())
	{
		memset(used,false,sizeof(used));
		for(int i=0;i<uN;i++)
		{
			if(Mx[i]==-1&&DFS(i))
				res++;
		}
	}
	return res;
}

/**********************************/

int main()
{
    //freopen("in.txt","r",stdin);
    //freopen("out.txt","w",stdout);

	scanf("%d%d",&n,&m);
	for(int i=0;i<n;i++) scanf("%d",a+i);
	for(int i=0;i<m;i++)
	{
		int x,y;
		scanf("%d%d",&x,&y);
		x--; y--;
		if(x%2==1) swap(x,y);
		/// Link Edge beteen x and y
		if(vis[x]==false) { fenjie(x,a[x]); vis[x]=true; }
		if(vis[y]==false) { fenjie(y,a[y]); vis[y]=true; }

		for(int j1=pt[x].from;j1<=pt[x].to;j1++)
		{
			for(int j2=pt[y].from;j2<=pt[y].to;j2++)
			{
				if(A2[j1]==A2[j2])
				{
					/// Link edge 
					uN=max(uN,j1);
					G[j1].push_back(j2);
				}
				else if(A2[j1]<A2[j2]) break;
			}
		}
	}

	uN++;
	cout<<MaxMatch()<<endl;
    
    return 0;
}

抱歉!评论已关闭.