题目链接:https://cn.vjudge.net/contest/281959#problem/C

题目大意:中文题目

具体思路:用网络流的思想,我们求得是最大的匹配数,那么我们按照二分图的形式去建边就可以了,加上超级源点和超级汇点,就可以用网络流跑了。

建边的时候,我们首先把每个数进行素因子分解,看一下当前的这个数能够被分解成多少个素数,奇数个的放在一个数组里,偶数个的放在另一个数组里面(如果两个点直接能匹配的话,就需要他们两个相除之后只能剩余一个素数)。对于当前的这条边的权值,我们是按照最大流进行的,所以需要建立负边,具体的注释在代码中解释吧。

AC代码:

 #include <iostream>
#include<stack>
#include<stdio.h>
#include<cmath>
#include<algorithm>
#include<queue>
#include<cstring>
using namespace std;
# define ll long long
const int maxn = +;
const int maxm = 3e5+;
const int mod = 1e9+;
const ll inf =1000000000000000ll;
struct node
{
int to;
ll cost;
ll w;
int nex;
} edge[maxm];
ll dis[maxm],prev[maxm],pree[maxm];
int vis[maxm];
int head[maxm],num;
ll t1[maxm],t2[maxm],t3[maxm];
ll tx[maxm],ty[maxm];
int viss[maxm],prim[maxm],primnum,isprim[maxm*];
void prime()
{
for(int i=; i<maxm; i++)
{
if(viss[i]==)
{
viss[i]=;
prim[++primnum]=i;
isprim[i]=;
for(int j=i; j<maxm; j+=i)
{
viss[j]=;
}
}
}
}
bool judge(ll t1,ll t2)
{
if(t1==||t2==)
return false;
if(t1<t2)
swap(t1,t2);
if(t1%t2!=)
return false;
t1/=t2;
// if(isprim[t1])
// return true;
// return false;
for(int i=;i<=primnum;i++){//判断是不是只剩下一个素数,这个地方有一个小的优化,我们看当前这个数是不是素数,只需要看到他的sqrt就可以了。
if(prim[i]>=t1)break;
if(t1%prim[i]==)return ;
}
return ;
}
void addedge(int fr,int to,ll w,ll cost)
{
edge[num].to=to;
edge[num].w=w;
edge[num].cost=-cost;
edge[num].nex=head[fr];
head[fr]=num++;
edge[num].to=fr;
edge[num].w=;
edge[num].cost=cost;
edge[num].nex=head[to];
head[to]=num++;
}
bool spfa(int st,int ed)
{
memset(vis,,sizeof(vis));
memset(pree,-,sizeof(pree));
for(int i=; i<=ed; i++)
dis[i]=inf;
dis[st]=,vis[st]=;
queue<int>q;
q.push(st);
while(!q.empty())
{
int top=q.front();
q.pop();
vis[top]=;
for(int i=head[top]; i!=-; i=edge[i].nex)
{
int tmp=edge[i].to;
if(edge[i].w&&dis[tmp]>dis[top]+edge[i].cost)
{
dis[tmp]=dis[top]+edge[i].cost;
pree[tmp]=top;
prev[tmp]=i;
if(vis[tmp]==)
{
vis[tmp]=;
q.push(tmp);
}
}
}
}
return pree[ed]!=-;
}
ll mincostflow(int st,int ed)
{
ll ans=;
ll cost=;
while(spfa(st,ed))
{
ll minn=inf ;
for(int i=ed; i!=st; i=pree[i])
{
minn=min(minn,edge[prev[i]].w);
}
if(cost+minn*dis[ed]<=)//注意这个地方,我们建立的是负边。
{
cost+=dis[ed]*minn;
ans+=minn;
for(int i=ed; i!=st; i=pree[i])
{
edge[prev[i]].w-=minn;
edge[prev[i]^].w+=minn;
}
}
else //寻找临界点
{
ans-=(cost/dis[ed]);
return ans;
}
}
return ans;
}
int main()
{
prime();
int n;
memset(head,-,sizeof(head));
scanf("%d",&n);
// cout<<primnum<<endl;
for(int i=; i<=n; i++)
{
scanf("%lld",&t1[i]);
}
for(int i=; i<=n; i++)
{
scanf("%lld",&t2[i]);
}
for(int i=; i<=n; i++)
{
scanf("%lld",&t3[i]);
}
int num1=,num2=;
for(int i=; i<=n; i++)//预先处理
{
int tmp=t1[i],tt=;
for(int j=; j<=primnum; j++)
{
while(tmp%prim[j]==)
{
tmp/=prim[j];
tt++;
}
if(tmp==||tmp==)
break;
}
if(tt&)
tx[++num1]=i;
else
ty[++num2]=i;
}
for(int i=; i<=num1; i++)
{
for(int j=; j<=num2; j++)
{
if(judge(t1[tx[i]],t1[ty[j]]))
{
addedge(tx[i],ty[j],1e9,t3[tx[i]]*t3[ty[j]]);
}
}
}
for(int i=; i<=num1; i++)
{
addedge(,tx[i],t2[tx[i]],);
}
for(int i=; i<=num2; i++)
{
addedge(ty[i],n+,t2[ty[i]],);
}
ll ans=mincostflow(,n+);
printf("%lld\n",ans);
return ;
}

C - 数字配对 (网络流 最大费用最大流)的更多相关文章

  1. COGS738 [网络流24题] 数字梯形(最小费用最大流)

    题目这么说: 给定一个由n 行数字组成的数字梯形如下图所示.梯形的第一行有m 个数字.从梯形的顶部的m 个数字开始,在每个数字处可以沿左下或右下方向移动,形成一条从梯形的顶至底的路径.规则1:从梯形的 ...

  2. 网络流(最大费用最大流) :POJ 3680 Intervals

    Intervals Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 7218   Accepted: 3011 Descrip ...

  3. 网络流(最小费用最大流):POJ 2135 Farm Tour

    Farm Tour Time Limit: 1000ms Memory Limit: 65536KB This problem will be judged on PKU. Original ID: ...

  4. HDU 6118 度度熊的交易计划(网络流-最小费用最大流)

    度度熊参与了喵哈哈村的商业大会,但是这次商业大会遇到了一个难题: 喵哈哈村以及周围的村庄可以看做是一共由n个片区,m条公路组成的地区. 由于生产能力的区别,第i个片区能够花费a[i]元生产1个商品,但 ...

  5. 洛谷P4003 [国家集训队2017]无限之环 网络流 最小费用最大流

    题意简述 有一个\(n\times m\)棋盘,棋盘上每个格子上有一个水管.水管共有\(16\)种,用一个\(4\)位二进制数来表示当前水管向上.右.下.左有个接口.你可以旋转除了\((0101)_2 ...

  6. $loj\ 2031\ [SDOI2016]$数字配对 网络流

    正解:网络流 解题报告: 我永远喜欢$loj$! 显然先预处理哪些$a$之间可以连边,然后考虑建两排点,连流量为$c_{i}\cdot c_{j}$,然后$ST$连$inf$,跑个费用流? 然后现在碰 ...

  7. POJ-2516-Minimum Cost(网络流, 最小费用最大流)

    链接: https://vjudge.net/problem/POJ-2516 题意: Dearboy, a goods victualer, now comes to a big problem, ...

  8. Minimum Cost 【POJ - 2516】【网络流最小费用最大流】

    题目链接 题意: 有N个商家它们需要货物源,还有M个货物供应商,N个商家需要K种物品,每种物品都有对应的需求量,M个商家每种物品都是对应的存货,然后再是K个N*M的矩阵表示了K个物品从供货商运送到商家 ...

  9. 网络流--最小费用最大流MCMF模板

    标准大白书式模板 #include<stdio.h> //大概这么多头文件昂 #include<string.h> #include<vector> #includ ...

随机推荐

  1. Django的ORM常用查询操作总结(Django编程-3)

    Django的ORM常用查询操作总结(Django编程-3) 示例:一个Student model: class Student(models.Model): name=models.CharFiel ...

  2. VMware配置Linux中APPache服务器

    [软件] VMware    SecureCRT [镜像文件] Centos6.8   APPache软件包 [步骤] 1.将所需文件通过SCRT传入到虚拟机中 2.挂载镜像 2.1 将镜像挂载到mn ...

  3. spring boot 系列之五:spring boot 通过devtools进行热部署

    前面已经分享过四篇随笔: spring boot 系列之一:spring boot 入门 spring boot 系列之二:spring boot 如何修改默认端口号和contextpath spri ...

  4. jupyter快捷键

    jupyter快捷键(jupyter有两个模式,命令模式和编辑模式) 当前cell侧边为蓝色时,表示此时为命令模式,按Enter切换为编辑模式 当前cell侧边为绿色时,表示此时为编辑模式,按Esc切 ...

  5. 自学Aruba6.3-账号管理(web页面配置)

    点击返回:自学Aruba之路 自学Aruba6.3-账号管理(web页面配置) 1 管理员账号管理 Configuration---Administrator中 角色名称 说明 root 该角色允许管 ...

  6. 沉迷Link-Cut tree无法自拔之:[BZOJ3669][Noi2014] 魔法森林

    来自蒟蒻 \(Hero \_of \_Someone\) 的 \(LCT\) 学习笔记 $ $ 有一个很好的做法是 \(spfa\) ,但是我们不聊 \(spfa\) , 来聊 \(LCT\) \(L ...

  7. 面试 -- requestLayout、invalidate与postInvalidate区别

    requestLayout: 从方法名字可以知道,“请求布局”,那就是说,如果调用了这个方法,那么对于一个子View来说,应该会重新进行布局流程.但是,真实情况略有不同,如果子View调用了这个方法, ...

  8. SDL_BlitSurface

    SDL_BlitSurface Use this function to perform a fast surface copy to a destination surface. Contents ...

  9. A1005. Spell It Right

    Given a non-negative integer N, your task is to compute the sum of all the digits of N, and output e ...

  10. A1086. Tree Traversals Again

    An inorder binary tree traversal can be implemented in a non-recursive way with a stack. For example ...