• LOJ#6045. 「雅礼集训 2017 Day8」价 题解


    题目链接

    首先把价值取反,然后问题转换为求最大权值。

    考虑一个最小割模型:

    S连向药,容量INF+权值,割掉这条边相当于不选这个药;

    药连向药材,容量INF;

    药材连向T,容量INF,割掉这条边相当于选这个药材;

    不难发现在最小割方案中,割掉药连向药材的边是不优的。

    因为有完美匹配,所以对于任意左部点集合 (S) , (|N(S)| geq |S|,) 因此至少会割掉(n)条边。

    又因为边权加上了 (INF) ,所以不会割掉 (>n) 条边。

    因此不选的药的个数 + 选的药材个数 = n,所以可以得到选的药材个数 = 选的药的个数。

    然后跑一个最小割即可。

    (O(Dinic(n,n^2)))

    code :

    #include <bits/stdc++.h>
    #define LL long long
    using namespace std;
    template <typename T> void read(T &x){
    	x = 0; int f = 1; char ch = getchar();
    	while (!isdigit(ch)) {if (ch == '-') f = -1; ch = getchar();}
    	while (isdigit(ch)) {x = x * 10 + ch - '0'; ch = getchar();}
    	x *= f;
    }
    inline void write(int x){if (x > 9) write(x/10); putchar(x%10+'0'); }
    const int N = 305,V = N<<1,E = N*N,INF = 600000000;
    int To[E<<1],Ne[E<<1],Flow[E<<1],He[V],Now[V],_ = 1;
    inline void add(int x,int y,int flow){
    	++_; To[_] = y,Flow[_] = flow,Ne[_] = He[x],He[x] = _;
    	++_; To[_] = x,Flow[_] = 0,Ne[_] = He[y],He[y] = _;
    }
    int n,cntv,S,T; 
    int dis[V],Q[V],ql,qr;
    inline bool Bfs(){
    	int x,y,p;
    	memset(dis,0,cntv+1<<2),Q[ql=qr=1] = S,dis[S] = 1;
    	while (ql <= qr){
    		x = Q[ql],++ql;
    		for (p = He[x]; p ; p = Ne[p]) if (Flow[p] && !dis[y=To[p]]) dis[y] = dis[x] + 1,Q[++qr] = y;
    	}
    	return dis[T];
    }
    inline LL Dfs(int x,LL flow){
    	if (!flow || x == T) return flow;
    	LL rest = flow; int f,y,p;
    	for (p = Now[x]; p ; p = Ne[p]){
    		Now[x] = p; if (Flow[p] && dis[y=To[p]] == dis[x] + 1){
    			f = Dfs(y,min(rest,(LL)Flow[p])),Flow[p] -= f,rest -= f,Flow[p^1] += f;
    			if (!rest) return flow;
    		}
    	}
    	dis[x] = -233;
    	return flow - rest;
    }
    inline LL Dinic(){
    	LL sum = 0;
    	while (Bfs()) memcpy(Now,He,cntv+1<<2),sum += Dfs(S,1ll<<60);
    	return sum;
    }
    LL ans;
    int main(){
    	int i,j,k;
    	read(n),S = n<<1|1,T = S+1,cntv = T;
    	for (i = 1; i <= n; ++i){ read(k); while (k--) read(j),add(i,j+n,INF); }
    	for (i = 1; i <= n; ++i) read(j),ans -= j,add(S,i,INF-j),add(i+n,T,INF);
    	ans -= Dinic() - 1ll * INF * n;
    	cout << -ans << '
    ';
    	return 0;
    }
    
  • 相关阅读:
    Jocke的IOT之路--raspberrypi更换国内镜像
    利用PostMan 模拟上传/下载文件
    Java中的Lambda表达式
    设计模式之Jdk动态代理
    设计模式之代理模式
    Java内存模型及Java关键字 volatile的作用和使用说明
    JVM GC-----4、finalize()方法
    JVM GC-----3、垃圾对象的标记思路(二)
    JVM GC-----2、垃圾对象的标记思路(一)
    JVM GC-----1、垃圾回收算法
  • 原文地址:https://www.cnblogs.com/s-r-f/p/13662769.html
Copyright © 2020-2023  润新知