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

498C - Array and Operations 质因子分解+最大流

时间:2015-01-17 16:38:05      阅读:190      评论:0      收藏:0      [点我收藏+]

标签:

题目中说每一个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

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