[P4068] Luo Gu digital counterpart

topic

Topic links: https://www.luogu.com.cn/problem/P4068
have \ (n \) kinds of figures, the first \ (i \) species number is \ (a_i \) , there \ (b_i \) a, The weights are \ (C_i \) .
If the two numbers \ (a_i \) , \ (a_j \) satisfies, \ (a_i \) is \ (a_j \) multiples, and \ (\ frac {a_i} { a_j} \) is a prime number,
then this two numbers can be paired, and get (c_i \ times c_j \) \ value.
A number can only participate once paired, you can not participate in the pairing.
Under the premise of the sum of the value obtained is not less than zero, how many times were paired up to seek.

Thinking

We follow each number after the decomposition of the quality factor prime factors (not heavy) number parity divided into two categories, obviously any two numbers of the same class can not be paired because they must have an even number of commercial quality factor, so business is certainly not a prime number.
So these two sets is a bipartite graph. We consider the following construct:

  • Set a \ (a [i] \) of the quality factor has an odd number, from the source to the point (I \) \ even a flow \ (C [I] \) , 0 the cost side.
  • Set a \ (a [i] \) is an even number of prime factors, from \ (I \) to connect a sink flow \ (C [I] \) , 0 the cost side.
  • If the two different sets of points \ (i, j \) can be paired (provided \ (I \) prime factor has an odd number), then the \ (I \) to \ (J \) is connected to a flow \ ( + \ infty \) , a cost of \ (c [i] \ times c [j] \) side.

The next largest cost maximum flow can run. The maximum flow is the answer.
But the costs and the general cost flow stream is different, because the general cost flow requirement is the maximum flow rate with maximum / small time, and this problem requires "the sum of the value of not less than 0," that is the cost of not less than 0 maximum flow.
Obviously every longest longest road when the road is not more than the last time augmented augmented, if this longest path length is not negative, then obviously the better; otherwise it will certainly be bigger and more under the premise of the cost of not less than 0 well, because the back of augmenting the longest road will be shorter, so less income.

Code

#include <queue>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;

const int N=210,M=6e5,Inf=1e9;
int a[N],b[N],c[N],head[N],p[N],pre[N];
int n,S,T,tot=1;
ll maxflow,cost,dis[N];
bool vis[N];

struct edge
{
    int next,to,from,flow;
    ll cost;
}e[M];

void add(int from,int to,int flow,ll cost)
{
    e[++tot].to=to;
    e[tot].from=from;
    e[tot].flow=flow;
    e[tot].cost=cost;
    e[tot].next=head[from];
    head[from]=tot;
}

bool spfa()
{
    memset(dis,-0x3f3f3f3f,sizeof(dis));
    memset(vis,0,sizeof(vis));
    queue<int> q;
    q.push(S); dis[S]=0;
    while (q.size())
    {
        int u=q.front();
        q.pop();
        vis[u]=0;
        for (int i=head[u];~i;i=e[i].next)
        {
            int v=e[i].to;
            if (e[i].flow && dis[v]<dis[u]+e[i].cost)
            {
                dis[v]=dis[u]+e[i].cost;
                pre[v]=i;
                if (!vis[v])
                {
                    q.push(v);
                    vis[v]=1;
                }
            }
        }
    }
    return dis[T]>-1e18;
}

bool addflow()
{
    ll minflow=1e18;
    for (int x=T;x!=S;x=e[pre[x]].from)
        minflow=min(minflow,1LL*e[pre[x]].flow);
    if (dis[T]<0) minflow=min(minflow,cost/(-dis[T]));
    for (int x=T;x!=S;x=e[pre[x]].from)
    {
        e[pre[x]].flow-=minflow;
        e[pre[x]^1].flow+=minflow;
    }
    maxflow+=minflow;
    cost+=minflow*dis[T];
}

void mcmf()
{
    while (spfa())
    {
        if (cost+dis[T]<0) return;
        addflow();
    }
}

int main()
{
    S=N-1; T=N-2;
    memset(head,-1,sizeof(head));
    scanf("%d",&n);
    for (int i=1;i<=n;i++) scanf("%d",&a[i]);
    for (int i=1;i<=n;i++) scanf("%d",&b[i]);
    for (int i=1;i<=n;i++) scanf("%d",&c[i]);
    for (int i=1;i<=n;i++)
    {
        int x=a[i];
        for (int j=2;j*j<=x;j++)
            for (;x%j==0;x/=j) p[i]++;
        if (x>1) p[i]++;
        if (p[i]&1) add(S,i,b[i],0),add(i,S,0,0);
            else add(i,T,b[i],0),add(T,i,0,0);
    }
    for (int i=1;i<=n;i++)
        for (int j=1;j<=n;j++)
            if ((p[i]&1) && abs(p[i]-p[j])==1 && (!(a[i]%a[j]) || !(a[j]%a[i])))
                add(i,j,Inf,1LL*c[i]*c[j]),add(j,i,0,-1LL*c[i]*c[j]);
    mcmf();
    printf("%lld\n",maxflow);
    return 0;
}

Guess you like

Origin www.cnblogs.com/stoorz/p/12527030.html