zoukankan      html  css  js  c++  java
  • BZOJ 4514: [Sdoi2016]数字配对

    4514: [Sdoi2016]数字配对

    Time Limit: 10 Sec  Memory Limit: 128 MB
    Submit: 1606  Solved: 608
    [Submit][Status][Discuss]

    Description

    有 n 种数字,第 i 种数字是 ai、有 bi 个,权值是 ci。
    若两个数字 ai、aj 满足,ai 是 aj 的倍数,且 ai/aj 是一个质数,
    那么这两个数字可以配对,并获得 ci×cj 的价值。
    一个数字只能参与一次配对,可以不参与配对。
    在获得的价值总和不小于 0 的前提下,求最多进行多少次配对。

    Input

    第一行一个整数 n。
    第二行 n 个整数 a1、a2、……、an。
    第三行 n 个整数 b1、b2、……、bn。
    第四行 n 个整数 c1、c2、……、cn。 

    Output

     一行一个数,最多进行多少次配对

    Sample Input

    3
    2 4 8
    2 200 7
    -1 -2 1

    Sample Output

    4

    HINT

     n≤200,ai≤10^9,bi≤10^5,∣ci∣≤10^5

    Source

    鸣谢Menci上传

    分析:

    其实不难发现这是一个网络流的题目...

    然后考虑如何建图...

    我们发现题目中有用的信息大概就只有一句话了:

    若两个数字 ai、aj 满足,ai 是 aj 的倍数,且 ai/aj 是一个质数,

    于是,我们考虑如何利用这句话...如果我们把$a_x$分解质因数,那么如果存在$frac{a_i}{a_j}=p$,那么就代表$a_i$的$x$个质因子里面有$x-1$和$a_j$的指数相同,并且剩下的那个质因子的指数比$a_j$多$1$,于是,我们考虑记$f[i]$代表$a_i$的质因子指数之和,那么一定是$f[i]$为奇数的点和$f[i]$为偶数的点之间右边相连,这就告诉我们这是一张二分图...

    于是我们从$S$向所有的$f[i]$为奇数的点连$<S,i,b[i],0>$的边,从$f[i]$为偶数的点向$T$连$<i,T,b[i],0>$的边,然后对于所有合法的点对之间从奇数$f[i]$向偶数$f[i]$连$<x,y,inf,c[x]*x[y]>的边,然后如果要满足费用不小于$0$,那么我们跑最大费用最大流,如果当前增广的流更新答案之后答案不合法就直接停止增广输出答案...

    一定要抓住题目中给出的信息进行转化,多去考虑和算法有关的性质...

    代码:

    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<queue>
    #include<map>
    //by NeighThorn
    #define inf 0x3f3f3f3f3f3f3f
    using namespace std;
    
    const int maxn=200+5,maxm=32000+5,maxe=100000+5;
    
    int n,a[maxn],b[maxn],c[maxn];
    int cnt,no[maxn],vis[maxm],pri[maxm];
    int S,T,hd[maxn],fl[maxe],to[maxe],nxt[maxe],Min[maxn],from[maxn];
    long long w[maxe],dis[maxn];
    
    map<int,int> mp;
    
    inline void prework(void){
    	for(int i=2;i<=32000;i++){
    		if(!vis[i])
    			vis[i]=1,pri[++cnt]=i,mp[i]=1;
    		for(int j=1;j<=cnt&&pri[j]*i<=32000;j++){
    			vis[i*pri[j]]=1;
    			if(i%pri[j]==0) break;
    		}
    	}
    }
    
    inline void add(int x,int y,int s,long long l){
    	w[cnt]= l;fl[cnt]=s;to[cnt]=y;nxt[cnt]=hd[x];hd[x]=cnt++;
    	w[cnt]=-l;fl[cnt]=0;to[cnt]=x;nxt[cnt]=hd[y];hd[y]=cnt++;
    }
    
    inline bool spfa(void){
    	for(int i=S;i<=T;i++) dis[i]=-inf,Min[i]=0x3f3f3f3f;
    	queue<int> q;q.push(S),dis[S]=0;vis[S]=1;
    	while(!q.empty()){
    		int top=q.front();q.pop();vis[top]=0;
    		for(int i=hd[top];i!=-1;i=nxt[i])
    			if(fl[i]&&dis[to[i]]<dis[top]+w[i]){
    				from[to[i]]=i;
    				dis[to[i]]=dis[top]+w[i];
    				Min[to[i]]=min(Min[top],fl[i]);
    				if(!vis[to[i]])
    					vis[to[i]]=1,q.push(to[i]);
    			}
    	}
    	return dis[T]!=-inf;
    }
    
    inline long long find(void){
    	for(int i=T;i!=S;i=to[from[i]^1])
    		fl[from[i]]-=Min[T],fl[from[i]^1]+=Min[T];
    	return dis[T]*Min[T];
    }
    
    inline int mcmf(void){
    	long long t,mincost=0,maxflow=0;
    	while(spfa()){
    		t=find();
    		if(mincost+t>=0) mincost+=t,maxflow+=Min[T];
    		else{
    			maxflow+=mincost/abs(dis[T]);
    			return maxflow;
    		}
    	}
    	return maxflow;
    }
    
    signed main(void){
    	scanf("%d",&n);prework();S=0;
    	memset(hd,-1,sizeof(hd));T=n+1;
    	memset(vis,0,sizeof(vis));
    	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,tmp;i<=n;i++){
    		tmp=a[i];
    		for(int j=1;j<=cnt;j++)
    			while(tmp%pri[j]==0)
    				no[i]++,tmp/=pri[j];
    		if(tmp>1) no[i]++,mp[tmp]=1;
    	}
    	for(int i=1;i<=n;i++)
    		if(no[i]&1)
    			add(S,i,b[i],0);
    		else
    			add(i,T,b[i],0);
    	for(int i=1;i<=n;i++)
    		for(int j=1;j<=n;j++)
    			if(a[i]%a[j]==0&&mp.find(a[i]/a[j])!=mp.end()){
    				if(no[i]&1) add(i,j,0x3f3f3f3f,1LL*c[i]*c[j]);
    				else add(j,i,0x3f3f3f3f,1LL*c[i]*c[j]);
    			}
    	printf("%d
    ",mcmf());
    	return 0;
    }
    

      


    By NeighThorn

  • 相关阅读:
    会话:Cookie、Session
    Response:HTTP响应、重定向、验证码、ServletContext对象
    javabean 深拷贝
    条形码生成工具类
    java zxing 生成条形码和二维吗
    强大的httpClientUtils
    Java处理图片工具类
    生成二维码
    过滤掉map集合中key或value为空的值
    将异常堆栈信息转换成字符串
  • 原文地址:https://www.cnblogs.com/neighthorn/p/6704396.html
Copyright © 2011-2022 走看看