题目链接: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. NVIDIA面目生成器再做突破

    导读 NVIDIA创建的AI系统“GAN”可以通过对图像数据库的学习,来随机生成超逼真人脸照片而一炮走红,经过长时间的研发与晚上目前这套系统已经有了极大的进步.除了可以自主学习之外,生成的内容逼真,让 ...

  2. python异常提示表

    Python常见的异常提示及含义对照表如下: 异常名称 描述 BaseException 所有异常的基类 SystemExit 解释器请求退出 KeyboardInterrupt 用户中断执行(通常是 ...

  3. 使用vscode 编写Markdown文件

    markdown简单语法参考下面简单事例: # 一级标题 1. 有序列表1 >1. 有序列表1 >>- *test1* >>- **test2** >>- * ...

  4. Luogu4512 【模板】多项式除法(多项式求逆+NTT)

    http://blog.miskcoo.com/2015/05/polynomial-division 好神啊! 通过翻转多项式消除余数的影响,主要原理是商只与次数不小于m的项有关. #include ...

  5. python 模块 - 序列化 json 和 pickle

    1,引入 之前我们学习过用eval内置方法可以将一个字符串转成python对象,不过,eval方法是有局限性的,对于普通的数据类型,json.loads和eval都能用,但遇到特殊类型的时候,eval ...

  6. DeBruijin HDU - 2894(????????)

    题意: 莫名其妙 看不懂..只能靠别人的题意混日子 a完就懂了  就是 POJ1392  不求第k个了  直接输出这个路径 emm ...就改了一下那个代码 #include <iostream ...

  7. SharePoint 2013 event id 8321 错误

    SharePoint 2013里会报8321的错误: A certificate validation operation took 15011.1412 milliseconds and has e ...

  8. pandas 从入门到遗忘

    读取大文件(内存有限): import pandas as pd reader = pd.read_csv("tap_fun_test.csv", sep=',', iterato ...

  9. eclipse index 不工作 F3 不能找到头文件

    To add paths containing code to parse, follow these steps :1. Right click on the project2. Select Pr ...

  10. A1102. Invert a Binary Tree

    The following is from Max Howell @twitter: Google: 90% of our engineers use the software you wrote ( ...