• LG 1791 人员雇佣


    题面

    题解

    最小割

    每个人建一个点,用该点与 (S)(T) 连通表示不取或取,割断边要支付代价。

    可以将两人同时选的收益转化为选人的收益和二选一的代价:

    (X_iin{0,1}) 表示不选/选,则 (X_i imes X_j=frac{1}{2}(X_i+X_j-[X_i eq X_j]))

    于是点 (i)(S) 连边 (A_i) ,与 (T) 连边 (sum_j E_{i,j})

    (i) 与点 (j) 连边 (2 imes E_{i,j}) (均为无向边)

    求最小割 (Min)(Ans=sum_{i,j} E_{i,j}-Min)

    代码

    //https://www.luogu.com.cn/problem/P1791
    //20211023 AliCCC
    
    #include <cstdio>
    #include <queue>
    #include <algorithm>
    
    using std::min;
    using std::queue;
    
    const long long LONF=4567891012345678910LL;
    const int MAXN=1011;
    const int MAXV=MAXN<<1;
    const int MAXE=(MAXN<<1)+(MAXN*MAXN);	//undirected
    
    int N;
    
    int A[MAXN];
    
    int Ee[MAXN][MAXN];
    
    struct Vert{
    	int FE;
    	int Lev, Bfn;
    } V[MAXV];
    
    int Vcnt;
    int Sink, Sour;
    int P[MAXN];
    
    struct Edge{
    	int y, next;
    	long long f;
    } E[MAXE<<1];
    
    int Ecnt=2;
    
    void addE(const int &a, const int &b, const long long &f){
    	E[Ecnt].y=b;E[Ecnt].next=V[a].FE;V[a].FE=Ecnt;E[Ecnt].f=f;++Ecnt;
    	E[Ecnt].y=a;E[Ecnt].next=V[b].FE;V[b].FE=Ecnt;E[Ecnt].f=f;++Ecnt;
    }
    
    int BFN;
    
    queue<int> Q;
    
    bool BFS(int at=Sour){
    	++BFN;
    	V[at].Lev=1;
    	Q.push(at);
    	V[at].Bfn=BFN;
    	while(!Q.empty()){
    		at=Q.front();Q.pop();
    		for(int k=V[at].FE, to;k;k=E[k].next){
    			if(E[k].f<=0)	continue;
    			to=E[k].y;
    			if(V[to].Bfn==BFN)	continue;
    			V[to].Lev=V[at].Lev+1;
    			Q.push(to);
    			V[to].Bfn=BFN;
    		}
    	}
    	return V[Sink].Bfn==BFN;
    }
    
    long long DFS(int at=Sour, long long inc=LONF){
    	if(at==Sink || inc<=0LL)	return inc;
    	long long ret=0LL, out;
    	for(int k=V[at].FE, to;k;k=E[k].next){
    		if(E[k].f<=0)	continue;
    		to=E[k].y;
    		if(V[to].Lev!=V[at].Lev+1)	continue;
    		out=DFS(to, min(E[k].f, inc));
    		inc-=out;E[k].f-=out;
    		ret+=out;E[k^1].f+=out;
    	}
    	if(inc>0LL)	V[at].Lev=-1;
    	return ret;
    }
    
    long long DINIC(){
    	long long ret=0LL;
    	while(BFS()){
    		ret+=DFS();
    		// for(int i=0;i<Ecnt;++i){
    		// 	printf("%d %d %lld
    ", E[i].y, E[i].next, E[i].f);
    		// }
    		// printf("--%lld
    ", ret);
    		// puts("");
    	}
    	return ret;
    }
    
    int main(){
    	
    	scanf("%d", &N);
    	
    	Sour=++Vcnt;Sink=++Vcnt;
    	for(int i=1;i<=N;++i)	P[i]=++Vcnt;
    	
    	for(int i=1;i<=N;++i)	scanf("%d", &A[i]);
    	
    	for(int i=1;i<=N;++i){
    		addE(Sour, P[i], A[i]);
    	}
    	
    	long long Ans=0LL;
    	
    	for(int i=1;i<=N;++i){
    		long long tmp=0LL;
    		for(int j=1;j<=N;++j){
    			scanf("%d", &Ee[i][j]);
    			if(Ee[i][j])	addE(P[i], P[j], Ee[i][j]);
    			tmp+=Ee[i][j];Ans+=Ee[i][j];
    		}
    		addE(Sink, P[i], tmp);
    	}
    	
    	Ans-=DINIC();
    	
    	printf("%lld
    ", Ans);
    	
    	return 0;
    }
    

    后记

    其实 (0leq X_ileq 1)(max sum_{i,j} X_iX_jE_{i,j}-sum_{i,j} [X_i>X_j]E_{i,j}-sum_{i}X_iA_i) 是比较经典的线性规划式子,但 Pickupwin 发现自己不会线性规划转网络流了 TAT

    求大佬指点 [可怜]

  • 相关阅读:
    LAMP网站架构解释
    ftp--pureftpd1.0.46
    给远程主机起别名
    ssh修改端口号并进行远程访问
    ssh使两台机器建立连接
    Linux搭建svn服务
    centos上git搭建
    centos上Jenkins搭建
    kvm安装准备
    服务器Java环境配置
  • 原文地址:https://www.cnblogs.com/Pickupwin/p/LG-1791.html
Copyright © 2020-2023  润新知