C - 数字配对 (网络流 最大费用最大流)
题目链接: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 - 数字配对 (网络流 最大费用最大流)的更多相关文章
- COGS738 [网络流24题] 数字梯形(最小费用最大流)
题目这么说: 给定一个由n 行数字组成的数字梯形如下图所示.梯形的第一行有m 个数字.从梯形的顶部的m 个数字开始,在每个数字处可以沿左下或右下方向移动,形成一条从梯形的顶至底的路径.规则1:从梯形的 ...
- 网络流(最大费用最大流) :POJ 3680 Intervals
Intervals Time Limit: 5000MS Memory Limit: 65536K Total Submissions: 7218 Accepted: 3011 Descrip ...
- 网络流(最小费用最大流):POJ 2135 Farm Tour
Farm Tour Time Limit: 1000ms Memory Limit: 65536KB This problem will be judged on PKU. Original ID: ...
- HDU 6118 度度熊的交易计划(网络流-最小费用最大流)
度度熊参与了喵哈哈村的商业大会,但是这次商业大会遇到了一个难题: 喵哈哈村以及周围的村庄可以看做是一共由n个片区,m条公路组成的地区. 由于生产能力的区别,第i个片区能够花费a[i]元生产1个商品,但 ...
- 洛谷P4003 [国家集训队2017]无限之环 网络流 最小费用最大流
题意简述 有一个\(n\times m\)棋盘,棋盘上每个格子上有一个水管.水管共有\(16\)种,用一个\(4\)位二进制数来表示当前水管向上.右.下.左有个接口.你可以旋转除了\((0101)_2 ...
- $loj\ 2031\ [SDOI2016]$数字配对 网络流
正解:网络流 解题报告: 我永远喜欢$loj$! 显然先预处理哪些$a$之间可以连边,然后考虑建两排点,连流量为$c_{i}\cdot c_{j}$,然后$ST$连$inf$,跑个费用流? 然后现在碰 ...
- POJ-2516-Minimum Cost(网络流, 最小费用最大流)
链接: https://vjudge.net/problem/POJ-2516 题意: Dearboy, a goods victualer, now comes to a big problem, ...
- Minimum Cost 【POJ - 2516】【网络流最小费用最大流】
题目链接 题意: 有N个商家它们需要货物源,还有M个货物供应商,N个商家需要K种物品,每种物品都有对应的需求量,M个商家每种物品都是对应的存货,然后再是K个N*M的矩阵表示了K个物品从供货商运送到商家 ...
- 网络流--最小费用最大流MCMF模板
标准大白书式模板 #include<stdio.h> //大概这么多头文件昂 #include<string.h> #include<vector> #includ ...
随机推荐
- BZOJ5306 HAOI2018染色(容斥原理+NTT)
容易想到枚举恰好出现S次的颜色有几种.如果固定至少有i种恰好出现S次,那么方案数是C(M,i)·C(N,i*S)·(M-i)N-i*S·(i*S)!/(S!)i,设为f(i). 于是考虑容斥,可得恰好 ...
- Tree 菜单 递归
转载:http://www.cnblogs.com/igoogleyou/archive/2012/12/17/treeview2.html 一,通过查询数据库的方法 ID 为主键,PID 表明数据之 ...
- MT【226】费马点两题
已知$z_1=2\sqrt{3}i,z_2=3,z_3=-3,|z_3-z_4|=2\sqrt{3},$则$|z_1-z_4|+|z_2-z_4|$的最小值为_____ 提示:费马点最小,取$Z_4( ...
- Sublime text3 插件HTML/CSS/JS prettify 格式化代码
1.首先安装插件 菜单的preference->packages control,然后输入install .. 回车,再输入HTML/CSS/JS prettify 再回车,重启后就可以了. 2 ...
- 【Luogu5108】仰望半月的夜空(后缀数组)
[Luogu5108]仰望半月的夜空(后缀数组) 题面 洛谷 题解 实名举报这题在比赛之前还不是这个样子的,还被我用SAM给水过去了 很明显求出\(SA\)之后就是按照\(SA\)的顺序从前往后考虑每 ...
- 洛谷 P1158 导弹拦截(不是那个DP) 解题报告
P1158 导弹拦截 题目描述 经过1111年的韬光养晦,某国研发出了一种新的导弹拦截系统,凡是与它的距离不超过其工作半径的导弹都能够被它成功拦截.当工作半径为0时,则能够拦截与它位置恰好相同的导弹. ...
- JAVA 泛型方法 和 静态方法泛型
/* // 泛型方法和静态方法泛型 泛型类定义的泛型 在整个类中有效 如果被方法使用 那么泛型类的对象明确要操作的具体类型后,所有要操作的类型就已经固定 为了让不同方法可以操作不同类型 而且类型还 ...
- 蛋白质结构模型和功能预测:I-TASSER工具的使用
I-TASSER是一款用于预测蛋白质结构和功能的工具,网站链接:https://zhanglab.ccmb.med.umich.edu/I-TASSER/ 具体描述如下: I-TASSER (Iter ...
- jdbc操作数据库(详细)
JDBC是由java编程语言编写的类及接口组成,同时它为程序开发人员提供了一组用于实现对数据库访问的JDBC API,并支持SQL语言.利用JDBC可以将JAVA代码连接到oracle.DB2.SQL ...
- mysql 在linux下的启动
启动与停止 1.启动 MySQL安装完成后启动文件mysql在/etc/init.d目录下,在需要启动时运行下面命令即可. [root@test1 init.d]# /etc/init.d/mysql ...