zoukankan      html  css  js  c++  java
  • bzoj2400 Spoj 839 Optimal Marks

    题面
    题目链接

    思路

    既然是异或预算,很容易想到按位操作。
    按位操作之后,每个点的权值就只有(0)(1)两个了,然后从(S)向所有权值为(0)的点连一条(INF)的边,从所有权值为(1)的点向(T)连一条(INF)的边。然后将原图中的边全都连成权值为(1)的边。然后求最小割。
    如果没有不确定的点权,那么很明显这样是对的。
    画出图来就可以知道,对于不确定的点权这样操作也是对的。
    这样就可以完成第一问了。
    然后考虑第二问。在满足最小割的情况下要求点权最小。也就是说。再使得最小割不变的情况下,每个点的权值尽量的为(0),也就是说尽量的割掉与(T)的连边。这样就有一个非常神奇的做法。
    将原图中的边不再连(1),而是连成(10000).然后从(S)向每个点连一条权值为(1)的边。画出图来就可以发现这样是对的。
    因为如果当前割掉与(S)的连边和割掉与(T)的连边同样优秀的话,如果割掉了与(S)的连边,那么还有一条与(S)相连为(1)的边。使得还有(1)的流量,肯定会不优秀。所以这种情况就会优先割掉与T的连边。

    代码

    /*
    * @Author: wxyww
    * @Date:   2019-02-09 11:35:38
    * @Last Modified time: 2019-02-10 07:53:05
    */
    #include<cstdio>
    #include<iostream>
    #include<cstdlib>
    #include<cmath>
    #include<ctime>
    #include<queue>
    #include<cstring>
    #include<bitset>
    using namespace std;
    typedef long long ll;
    #define int ll
    const int N = 2010,INF = 1e9;
    ll read() {
    	ll x=0,f=1;char c=getchar();
    	while(c<'0'||c>'9') {
    		if(c=='-') f=-1;
    		c=getchar();
    	}
    	while(c>='0'&&c<='9') {
    		x=x*10+c-'0';
    		c=getchar();
    	}
    	return x*f;
    }
    struct node {
    	int v,nxt,w,u;
    }e[N * 10];
    int head[N],ejs;
    void add(int u,int v,int w) {
    	e[++ejs].v = v;e[ejs].nxt = head[u];head[u] = ejs;e[ejs].w = w;
    	e[++ejs].v = u;e[ejs].nxt = head[v];head[v] = ejs;e[ejs].w = 0;
    }
    int n,m,w[N],U[N],V[N];
    int dep[N],S,T;
    queue<int>q;
    int bfs() {
    	memset(dep,0,sizeof(dep));
    	while(!q.empty()) q.pop();
    	dep[S] = 1;
    	q.push(S);
    	while(!q.empty()) {
    		int u = q.front();q.pop();
    		for(int i = head[u];i;i = e[i].nxt) {
    			int v = e[i].v;
    			if(!dep[v] && e[i].w) {
    				dep[v] = dep[u] + 1;
    				q.push(v);
    				if(v == T) return 1;
    			}
    		}
    	}
    	return 0;
    }
    int dfs(int u,int now) {
    	if(u == T) return now;
    	int ret = 0;
    	for(int i = head[u];i;i = e[i].nxt) {
    		int v = e[i].v;
    		if(e[i].w && dep[v] == dep[u] + 1) {
    			int k = dfs(v,min(now - ret,e[i].w));
    			e[i].w -= k;
    			e[i ^ 1].w += k;
    			ret += k;
    			if(ret == now) return now;
    		}
    	}
    	return ret;
    }
    int dinic() {
    	int ans = 0;
    	while(bfs()) ans += dfs(S,INF); 
    	return ans;
    }
    void build(int x) {
    	ejs = 1;
    	memset(head,0,sizeof(head));
    	for(int i = 1;i <= n;++i) {
    		if(w[i] >= 0) {
    			if(w[i] & x) add(i,T,INF),add(S,i,1);
    			else add(S,i,INF);
    		}
    		else add(S,i,1);
    	}
    	for(int i = 1;i <= m;++i) {
    		add(U[i],V[i],10000);add(V[i],U[i],10000);
    	}
    }
    signed main() {
    	n = read();m = read();
    	S = n + 1,T = S + 1;
    	for(int i = 1;i <= n;++i) w[i] = read();
    	for(int i = 1;i <= m;++i) U[i] = read(),V[i] = read();
    	int ans1 = 0,ans2 = 0;
    	for(int i = 0;i <= 31;++i) {
    		build(1 << i);
    		int K = dinic();
    		ans1 += K / 10000 * (1 << i);
    		ans2 += K % 10000 * (1 << i);
    	}
    	printf("%lld
    %lld
    ",ans1,ans2);
    	return 0;
    }
    
  • 相关阅读:
    darknet实时识别无法显示在窗口解决
    C# 获取当前打开的文件夹2
    C# 如何调试安装包
    C# 自定义文件格式并即时刷新注册表 非关闭explorer
    C# 获取当前打开的文件夹
    SQL Server里面导出SQL脚本(表数据的insert语句)
    windows平台安装redis服务
    C# 默认参数/可选参数需要注意
    webstrom使用
    office密匙
  • 原文地址:https://www.cnblogs.com/wxyww/p/10358656.html
Copyright © 2011-2022 走看看