题目链接: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. python 惰性求值 https://blog.csdn.net/Appleyk/article/details/77334221

    为什么调用的不是同一个函数呢 是因为调用函数后,函数的生命周期就结束了,再调用就是另一个函数了

  2. codeforces604B

    More Cowbell CodeForces - 604B Kevin Sun wants to move his precious collection of n cowbells from Na ...

  3. Linux环境变量PATH

    查看PATH:echo $PATH以添加mongodb server为列修改方法一:export PATH=/usr/local/mongodb/bin:$PATH//配置完后可以通过echo $PA ...

  4. Django-website 程序案例系列-5 模态对话框实现提交数据

    html代码: <!DOCTYPE html> <html lang="en"> <head> <meta charset="U ...

  5. JAVA内部类小结

    内部类的概念:定义在其他类里面的类叫做内部类,包含内部类的类叫做外部类: 内部类的作用:内部类主要是用来描述一个事物存在于另一个事物里面,依赖于外部事物存在的: 内部类的格式: 内部类的分类: 成员内 ...

  6. MT【23】用算术几何不等式证明数列极限存在

    评:如果不需要精确到3,上界的求法可以利用$$(1+\frac{1}{n})^n*\frac{1}{2}*\frac{1}{2}<(\frac{n+\frac{1}{n}*n+\frac{1}{ ...

  7. LOJ 2664. 「NOI2013」向量内积 解题报告

    #2664. 「NOI2013」向量内积 两个 \(d\) 维向量 \(A=[a_1, a_2 ,...,a_d]\) 与 \(B=[b_1 ,b_2 ,...,b_d]\) 的内积为其相对应维度的权 ...

  8. POJ 1958 Strange Towers of Hanoi 解题报告

    Strange Towers of Hanoi 大体意思是要求\(n\)盘4的的hanoi tower问题. 总所周知,\(n\)盘3塔有递推公式\(d[i]=dp[i-1]*2+1\) 令\(f[i ...

  9. yum 安装Mysql

    RHEL6.5-MySql-yum安装登录 客户端工具的使用mysql:Linux下提供了一个访问mysql服务器的客户端工具—mysql,其由mysql软件包提供,除了这些工具之外还有一些图形化界面 ...

  10. 爬虫json数据的处理

    在爬网页的过程中,最喜欢遇到的就是json数据接口,省了不少麻烦,但是json数据也有多种格式. 类型一:标准的json result = json.loads(html.text),将str转成py ...