• 【CF434D】Nanami's Power Plant 最小割


    【CF434D】Nanami's Power Plant

    题意:有n个二次函数$y=a_ix^2+b_ix+c_i$($a_i,b_i,c_i$是整数),第i个函数要求x的取值在$[l_i,r_i]$之间且为整数。你需要确定每个函数的x的取值,使得所有函数的函数值之和最大。还有m个限制,每条限制形如$u,v,d$,表示$x_ule x_v+d$。求最大函数值之和。

    $nle 50,mle 100,-100le l_ile r_ile 100$

    题解:傻逼了连切糕都忘了。

    对于一个方程,我们把它的所有可能取值按照x从小到大串成一串,首尾分别与S和T相连,其中第i个点和第i+1个点的边的容量为当$x=l+i-1$时的函数值(由于可能存在负数,我们给每条边的权值都加上一个大数,最后再把这个大数减去)。对于限制u,v,d,我们从u中所有代表$x_u=i$的点向v中代表$x_v=i-d$的点连一条容量inf的边,便完成了限制。

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    #include <queue>
    using namespace std;
    typedef long long ll;
    const ll big=1ll<<30;
    const ll inf=1ll<<50;
    int n,m,tot,S,T,cnt;
    ll ans;
    int L[60],R[60],to[200010],nxt[200010],head[12000],d[12000];
    int p[60][210];
    ll val[200010],A[60],B[60],C[60];
    queue<int> q;
    inline void add(int a,int b,ll c)
    {
    	to[cnt]=b,val[cnt]=c,nxt[cnt]=head[a],head[a]=cnt++;
    	to[cnt]=a,val[cnt]=0,nxt[cnt]=head[b],head[b]=cnt++;
    }
    ll dfs(int x,ll mf)
    {
    	if(x==T)	return mf;
    	int i;
    	ll temp=mf,k;
    	for(i=head[x];i!=-1;i=nxt[i])	if(val[i]&&d[to[i]]==d[x]+1)
    	{
    		k=dfs(to[i],min(temp,val[i]));
    		if(!k)	d[to[i]]=-1;
    		temp-=k,val[i]-=k,val[i^1]+=k;
    		if(!temp)	break;
    	}
    	return mf-temp;
    }
    inline int bfs()
    {
    	while(!q.empty())	q.pop();
    	int i,u;
    	memset(d,0,sizeof(d));
    	q.push(S),d[S]=1;
    	while(!q.empty())
    	{
    		u=q.front(),q.pop();
    		for(i=head[u];i!=-1;i=nxt[i])	if(val[i]&&!d[to[i]])
    		{
    			d[to[i]]=d[u]+1;
    			if(to[i]==T)	return 1;
    			q.push(to[i]);
    		}
    	}
    	return 0;
    }
    int main()
    {
    	//freopen("cf434D.in","r",stdin);
    	scanf("%d%d",&n,&m);
    	S=0,T=tot=1;
    	int i,j,a,b,c;
    	memset(head,-1,sizeof(head));
    	for(i=1;i<=n;i++)	scanf("%lld%lld%lld",&A[i],&B[i],&C[i]);
    	for(i=1;i<=n;i++)
    	{
    		scanf("%d%d",&L[i],&R[i]);
    		add(S,tot+1,inf);
    		for(j=L[i];j<=R[i];j++)
    		{
    			p[i][j-L[i]]=++tot;
    			add(tot,tot+1,big-(A[i]*j*j+B[i]*j+C[i]));
    		}
    		p[i][R[i]-L[i]+1]=++tot;
    		add(tot,T,inf);
    	}
    	for(i=1;i<=m;i++)
    	{
    		scanf("%d%d%d",&a,&b,&c);
    		for(j=max(L[b],L[a]-c);j<=min(R[b],R[a]-c)+1;j++)
    		{
    			add(p[a][j+c-L[a]],p[b][j-L[b]],inf);
    		}
    	}
    	while(bfs())	ans+=dfs(S,inf);
    	printf("%lld",big*n-ans);
    	return 0;
    }
  • 相关阅读:
    排列与组合
    C++构造函数虚函数例题
    排序
    Android相机是如何获取到图像的
    《Android进阶》之第七篇 NDK的使用
    递归相关题目
    华为模拟性格测试
    平衡二叉树
    Fragment回调接口应用间分享数据
    IOS中限制TextField中输入的类型以及长度
  • 原文地址:https://www.cnblogs.com/CQzhangyu/p/8723451.html
Copyright © 2020-2023  润新知