Codeforces Round #284 (Div. 1) C. Array and Operations (最大流)

来源:互联网 发布:渡边直美 知乎 编辑:程序博客网 时间:2024/05/18 03:12

题目地址:http://codeforces.com/contest/498/problem/C
分别分解出每个数字的质因子,然后第奇数个数字的质因子在左边集合,偶数个数字的质因子在右边集合,建立源点和汇点,然后根据每个数字含有的质因子的个数建边,跑一遍最大流即可。
代码如下:

#include <iostream>#include <string.h>#include <math.h>#include <queue>#include <algorithm>#include <stdlib.h>#include <map>#include <set>#include <stdio.h>#include <time.h>using namespace std;#define LL long long#define pi acos(-1.0)#pragma comment(linker, "/STACK:1024000000")const int mod=1e9+7;const int INF=0x3f3f3f3f;const double eqs=1e-9;const int MAXN=5000+10;int a[200];int head[MAXN], source, sink, nv, cnt;int cur[MAXN], num[MAXN], d[MAXN], pre[MAXN], q[MAXN], sum[110];struct node {        int u, v, cap, next;} edge[1000000];void add(int u, int v, int cap){        edge[cnt].v=v;        edge[cnt].cap=cap;        edge[cnt].next=head[u];        head[u]=cnt++;        edge[cnt].v=u;        edge[cnt].cap=0;        edge[cnt].next=head[v];        head[v]=cnt++;}void bfs(){        memset(num,0,sizeof(num));        memset(d,-1,sizeof(d));        int f1=0, f2=0, i;        d[sink]=0;        num[0]=1;        q[f1++]=sink;        while(f1>=f2) {                int u=q[f2++];                for(i=head[u]; i!=-1; i=edge[i].next) {                        int v=edge[i].v;                        if(d[v]==-1) {                                d[v]=d[u]+1;                                num[d[v]]++;                                q[f1++]=v;                        }                }        }}void isap(){        memcpy(cur,head,sizeof(cur));        bfs();        int flow=0, u=pre[source]=source, i;        while(d[source]<nv) {                if(u==sink) {                        int f=INF,pos;                        for(i=source; i!=sink; i=edge[cur[i]].v) {                                if(f>edge[cur[i]].cap) {                                        f=edge[cur[i]].cap;                                        pos=i;                                }                        }                        for(i=source; i!=sink; i=edge[cur[i]].v) {                                edge[cur[i]].cap-=f;                                edge[cur[i]^1].cap+=f;                        }                        flow+=f;                        u=pos;                }                for(i=cur[u]; i!=-1; i=edge[i].next) {                        if(d[edge[i].v]+1==d[u]&&edge[i].cap) {                                break;                        }                }                if(i!=-1) {                        cur[u]=i;                        pre[edge[i].v]=u;                        u=edge[i].v;                } else {                        if(--num[d[u]]==0) break;                        int mind=nv;                        for(i=head[u]; i!=-1; i=edge[i].next) {                                if(mind>d[edge[i].v]&&edge[i].cap) {                                        mind=d[edge[i].v];                                        cur[u]=i;                                }                        }                        d[u]=mind+1;                        num[d[u]]++;                        u=pre[u];                }        }        printf("%d\n",flow);}int gcd(int x, int y){        return y==0?x:gcd(y,x%y);}vector<int>vec[110], Num[110];void get(int x, int y){        int i, ans;        for(i=2; i*i<=x; i++) {                if(x%i) continue ;                vec[y].push_back(i);                ans=0;                while(x%i==0) {                        x/=i;                        ans++;                }                Num[y].push_back(ans);        }        if(x!=1) {                vec[y].push_back(x);                Num[y].push_back(1);        }}void init(){        memset(head,-1,sizeof(head));        cnt=0;}int main(){        int n, m, x, y, z, ans, i, sum1, sum2, j, num1, num2;        while(scanf("%d%d",&n,&m)!=EOF) {                for(i=1; i<=n; i++) {                        scanf("%d",&a[i]);                        vec[i].clear();                }                sum1=sum2=0;                sum[0]=0;                for(i=1; i<=n; i++) {                        get(a[i],i);                        if(i&1) {                                sum1+=vec[i].size();                                sum[i]=sum1;                        } else {                                sum2+=vec[i].size();                                sum[i]=sum2;                        }                }                //printf("%d %d\n",sum1,sum2);                source=0;                sink=sum1+sum2+1;                nv=sink+1;                init();                num1=num2=0;                for(i=1; i<=n; i++) {                        if(i&1) {                                for(j=0; j<vec[i].size(); j++) {                                        num1++;                                        add(source,num1,Num[i][j]);                                }                        } else {                                for(j=0; j<vec[i].size(); j++) {                                        num2++;                                        add(num2+sum1,sink,Num[i][j]);                                }                        }                }                while(m--) {                        scanf("%d%d",&x,&y);                        if(y&1) swap(x,y);                        int l=x==1?0:sum[x-2], r=sum[y-2];                        for(i=0; i<vec[x].size(); i++) {                                for(j=0; j<vec[y].size(); j++) {                                        if(vec[x][i]==vec[y][j]) {                                                add(l+i+1,sum1+r+j+1,min(Num[x][i],Num[y][j]));                                                break;                                        }                                }                        }                }                isap();        }        return 0;}
1 0
原创粉丝点击