zoukankan      html  css  js  c++  java
  • luoguP4068 [SDOI2016]数字配对

    题意

    看见配对数最多,想到这是最大流。看到代价,想到这是最大费用流。
    于是这题是最大费用最大流。
    做完了,撒花!

    我们发现这题没有明显的组别之分,也就是说我们并不知道建图时谁连源点谁连汇点。

    再次观察题中给出的配对的条件:(a_i)(a_j)的倍数且满足(frac{a_i}{a_j}in prime),即(a_i=k*a_j,kin prime)

    (cnt_x)表示(x)质因数分解后指数之和,如(cnt_{12}=3),因为(12=3^1*2^2,1+2=3)

    我们发现题中条件变为:(a_i)(a_j)的倍数且满足(cnt_{a_i}=cnt_{a_j}+1!!!)

    于是我们可以按照(cnt_{a_i})的奇偶性对(i)分类,奇数连源点,偶数连汇点,容量都为(b_i),费用为(0)

    之后就枚举每对((i,j)),满足条件就从(cnt)为奇数的向另一个连容量为(b_i*b_j),费用为(c_i*c_j)的边即可。

    如果没有这个限制题就已经做完了:“在获得的价值总和不小于(0)的前提下”

    为了处理这个限制,我们考虑(Dinic)的过程,我们每次(spfa)的求出的最长路必定是递减的,因为这是(Dinic)复杂度的保证。(可以去看(Dinic)的复杂度证明,就是用最长/短路总是变得更差证的)

    于是我们每次求出费用后就判断下加上是否会小于(0),不小于(0)就直接加上,不然就只加加上刚好不小于(0)的那一部分,之后(break)掉。

    code:

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int maxn=210;
    const ll inf=1e18;
    int n,cnt_edge=1,S,T;
    int a[maxn],b[maxn],c[maxn],head[maxn],cnt[maxn];
    ll dis[maxn];
    bool vis_prime[100010],vis[maxn];
    vector<int>prime;
    struct edge{int to,nxt;ll flow,cost;}e[(maxn*maxn)<<2];
    inline ll read()
    {
    	char c=getchar();ll res=0,f=1;
    	while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    	while(c>='0'&&c<='9')res=res*10+c-'0',c=getchar();
    	return res*f;
    }
    inline void add(int u,int v,ll w,ll c)
    {
    	e[++cnt_edge].nxt=head[u];
    	head[u]=cnt_edge;
    	e[cnt_edge].to=v;
    	e[cnt_edge].flow=w;
    	e[cnt_edge].cost=c;
    }
    inline void addflow(int u,int v,ll w,ll c){add(u,v,w,c);add(v,u,0,-c);}
    inline void pre_work()
    {
    	vis[1]=1;
    	for(int i=2;i<=100000;i++)
    	{
    		if(!vis_prime[i])prime.push_back(i);
    		for(unsigned int j=0;j<prime.size()&&i*prime[j]<=100000;j++)
    		{
    			vis_prime[i*prime[j]]=1;
    			if(i%prime[j]==0)break;
    		}
    	}
    }
    inline bool spfa()
    {
    	memset(vis,0,sizeof(vis));
    	for(int i=S;i<=T;i++)dis[i]=-inf;
    	queue<int>q;
    	q.push(S);dis[S]=0;vis[S]=1;
    	while(!q.empty())
    	{
    		int x=q.front();q.pop();vis[x]=0;
    		for(int i=head[x];i;i=e[i].nxt)
    		{
    			int y=e[i].to;
    			if(dis[y]<dis[x]+e[i].cost&&e[i].flow>0)
    			{
    				dis[y]=dis[x]+e[i].cost;
    				if(!vis[y])q.push(y),vis[y]=1;
    			}
    		}
    	}
    	return dis[T]!=-inf;
    }
    ll dfs(int x,ll lim)
    {
    	vis[x]=1;
    	if(x==T||lim<=0)return lim;
    	ll res=lim;
    	for(int i=head[x];i;i=e[i].nxt)
    	{
    		int y=e[i].to;
    		if(dis[y]!=dis[x]+e[i].cost||e[i].flow<=0||vis[y])continue;
    		ll tmp=dfs(y,min(res,e[i].flow));
    		res-=tmp;
    		e[i].flow-=tmp;e[i^1].flow+=tmp;
    		if(res<=0)break;
    	}
    	return lim-res;
    }
    inline ll Dinic()
    {
    	ll res=0,cost=0;
    	while(spfa())
    	{
    		ll flow=dfs(S,inf);
    		if(cost+flow*dis[T]>=0)res+=flow,cost+=flow*dis[T];
    		else 
    		{
    			res+=min(flow,cost/(-dis[T]));
    			break;
    		}
    	}
    	return res;
    }
    int main()
    {
    	//freopen("test.in","r",stdin);
    	//freopen("test.out","w",stdout);
    	pre_work();
    	n=read();
    	for(int i=1;i<=n;i++)a[i]=read();
    	for(int i=1;i<=n;i++)b[i]=read();
    	for(int i=1;i<=n;i++)c[i]=read();
    	for(int i=1;i<=n;i++)
    	{	
    		int tmp=a[i];
    		for(unsigned int j=0;j<prime.size()&&1ll*prime[j]*prime[j]<=tmp;j++)
    			while(tmp%prime[j]==0)cnt[i]++,tmp/=prime[j];
    		if(tmp>1)cnt[i]++;
    	}
    	S=0,T=n+1;
    	for(int i=1;i<=n;i++)
    		if(cnt[i]&1)addflow(S,i,b[i],0);
    		else addflow(i,T,b[i],0);
    	for(int i=1;i<=n;i++)
    		for(int j=i+1;j<=n;j++)
    		{
    			int x=a[i],y=a[j];
    			if(((x%y!=0)&&(y%x!=0))||abs(cnt[i]-cnt[j])!=1)continue;
    			x=i,y=j;
    			if(cnt[y]&1)swap(x,y);
    			addflow(x,y,1ll*b[x]*b[y],1ll*c[x]*c[y]);
    		}
    	printf("%lld",Dinic());
    	return 0;
    }
    
  • 相关阅读:
    CSS 整形与优化工具
    下面是小图,点一下上面就会出现大图
    javascript技巧大全
    div实现flash的遮照效果
    表格动态添加删除行
    云计算新模式将终结传统外包模式[转]
    源码过瑞星
    批处理创建、访问、重命名、删除畸形文件/文件夹
    //过360云查杀的代码
    NC反弹提权教程
  • 原文地址:https://www.cnblogs.com/nofind/p/12109835.html
Copyright © 2011-2022 走看看