• ARC107F Sum of Abs


    一个图,你要删去若干个点。删点的代价为(A_i),最终得到的图的价值为所有连通块的(B_i)之和的绝对值。

    最大化(价值-代价)

    (n,mle 300)


    可以转化成:你要给若干个点赋上(+1,-1,delete),使得有边相连的不能一个为(+1)一个为(-1)

    不考虑限制先得到假的最优解,然后对于以上三种情况分别求出它们的代价。

    最小割。将每个点(i)拆成(X_i)(Y_i)。如果(X_i,Y_iin S),则表示(+1);如果(X_i,Y_iin T),则表示(-1);如果(X_iin S,Y_i in T),则表示(delete)。为了避免(Y_iin S,X_i in T)的情况,一开始连边((Y_i,X_i,infty))

    如果有边((u,v)),连((Y_u,X_v,infty),(Y_v,X_u,infty))


    using namespace std;
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #define N 310
    #define INF 1000000000
    int n,m;
    int a[N],b[N];
    struct EDGE{
    	int to,c;
    	EDGE *las;
    } e[N*10];
    int ne;
    EDGE *last[N*2];
    int S,T;
    void link(int u,int v,int c){
    	e[ne]={v,c,last[u]};
    	last[u]=e+ne++;
    }
    #define rev(ei) (e+(int((ei)-e)^1))
    EDGE *cur[N*2];
    int dis[N*2],gap[N*2],BZ;
    int dfs(int x,int s){
    	if (x==T)
    		return s;
    	int have=0;
    	for (EDGE *&ei=cur[x];ei;ei=ei->las){
    		if (ei->c && dis[x]==dis[ei->to]+1){
    			int t=dfs(ei->to,min(ei->c,s-have));
    			ei->c-=t,rev(ei)->c+=t,have+=t;
    			if (have==s)	
    				return s;
    		}
    	}
    	cur[x]=last[x];
    	if (!--gap[dis[x]])
    		BZ=0;
    	dis[x]++;
    	gap[dis[x]]++;
    	return have;
    }
    int flow(){
    	gap[0]=T;
    	BZ=1;
    	int res=0;
    	while (BZ)
    		res+=dfs(S,INF);
    	return res;
    }
    int main(){
    //	freopen("in.txt","r",stdin);
    //	freopen("out.txt","w",stdout);
    	scanf("%d%d",&n,&m);
    	for (int i=1;i<=n;++i) scanf("%d",&a[i]);
    	for (int i=1;i<=n;++i) scanf("%d",&b[i]);
    	S=n+n+1,T=n+n+2;
    	int sum=0;
    	for (int i=1;i<=n;++i)
    		if (b[i]>0){
    			link(S,i,2*b[i]),link(i,S,0);
    			link(i,i+n,b[i]+a[i]),link(i+n,i,INF);
    			sum+=b[i];
    //			printf("%d %d %d
    ",S,i,2*b[i]);
    //			printf("%d %d %d
    ",i,i+n,b[i]+a[i]);
    		}
    		else{
    			link(i+n,T,-2*b[i]),link(T,i+n,0);
    			link(i,i+n,-b[i]+a[i]),link(i+n,i,INF);
    			sum+=-b[i];
    //			printf("%d %d %d
    ",i+n,T,-2*b[i]);
    //			printf("%d %d %d
    ",i,i+n,-b[i]+a[i]);
    		}
    	for (int i=1;i<=m;++i){
    		int u,v;
    		scanf("%d%d",&u,&v);
    		link(u+n,v,INF),link(v,u+n,0);
    		link(v+n,u,INF),link(u,v+n,0);
    	}
    	printf("%d
    ",sum-flow());
    	return 0;
    }
    
  • 相关阅读:
    大数据平台Hadoop集群搭建
    分布式文件系统之FastDFS安装部署
    Nginx反代MogileFS集群
    分布式文件系统之MogileFS的安装使用
    高可用服务之Keepalived利用脚本实现服务的可用性检测
    高可用服务之Keepalived高可用LVS集群
    高可用服务之Keepalived邮件通知配置
    高可用服务之Keepalived基础入门
    高可用集群corosync+pacemaker之pcs安装使用
    高可用集群corosync+pacemaker之crmsh使用(二)
  • 原文地址:https://www.cnblogs.com/jz-597/p/13908550.html
Copyright © 2020-2023  润新知