• CodeChef 2020 November Challenge


    CodeChef 2020 November Challenge - Red-Black Boolean Expression

    吐槽:这题很蠢,很套路

    题目大意:

    给定(n)个布尔变量(x_i),每个变量有其反变量$ overline {x_i}$

    (n)组关系(a_i,b_i),要求(a_ilor b_i)为真

    并且保证所有(a_i,b_i)关系构成一张二分图,其中(x_i)(overline{x_i})有一条边相连

    给定每个变量的初始值(s_i),以及翻转其所需的代价(C_i),求最小满足条件的代价

    [ ]

    (a_ilor b_i)为真即不存在(a_i,b_i)均为假的情况

    如果是2-sat上的理解,即可以由(a_i)假推(b_i)真,(b_i)假推(a_i)真,但是(2-sat)没法带权

    由于题目保证了关系的二分图性质,不妨把所有变量分成两个集合(A,B)

    这个问题令人联想到网络流最小割模型,我们用一条边((u,v))限制((u,v))不同时为假的情况

    对于(A)中的点,我们令源点(S)(u)连的边((S,u,w))表示(u)变成(0)所需代价,令((u,T,w))表示(u)变成1的代价

    对于(B)中的点,采取相反的连接方式

    任意一个关系的两点不在同一集合,不妨对于(uin A)的情况考虑,实际上可以分为两类考虑

    1.((u,v))不同时为0,那么连接一条边((v,u,infty)),表示如果合法必然有一条让(u)(v)变成1的边被割掉

    2.((u,v))不同时为1,连接一条边((v,u,infty)),原理类似

    然后就可以跑网络流最小割了

    #include<bits/stdc++.h>
    using namespace std;
    
    typedef long long ll;
    typedef double db;
    typedef unsigned long long ull;
    typedef pair <int,int> Pii;
    #define reg register
    #define pb push_back
    #define mp make_pair
    #define Mod1(x) ((x>=P)&&(x-=P))
    #define Mod2(x) ((x<0)&&(x+=P))
    #define rep(i,a,b) for(int i=a,i##end=b;i<=i##end;++i)
    #define drep(i,a,b) for(int i=a,i##end=b;i>=i##end;--i)
    template <class T> inline void cmin(T &a,T b){ ((a>b)&&(a=b)); }
    template <class T> inline void cmax(T &a,T b){ ((a<b)&&(a=b)); }
    
    char IO;
    template <class T=int> T rd(){
    	T s=0; int f=0;
    	while(!isdigit(IO=getchar())) if(IO=='-') f=1;
    	do s=(s<<1)+(s<<3)+(IO^'0');
    	while(isdigit(IO=getchar()));
    	return f?-s:s;
    }
    
    const int N=1e5+10,INF=1e9+10;
    
    int n,m,S,T;
    char s[N];
    struct Edge{
    	int to,nxt,w;
    }e[N<<1];
    int head[N],ecnt=1;
    void AddEdge(int u,int v,int w) {
    	e[++ecnt]=(Edge){v,head[u],w};
    	head[u]=ecnt;
    }
    void Link(int u,int v,int w){ 
    	AddEdge(u,v,w),AddEdge(v,u,0);
    }
    
    int F[N],X[N],Y[N],col[N],A[N];
    // 这里我用带权并查集实现了二分图
    int Find(int x){ 
    	if(F[x]==x) return x;
    	int f=F[x]; F[x]=Find(F[x]);
    	col[x]^=col[f];
    	return F[x];
    }
    
    int dis[N];
    int Bfs() {
    	rep(i,1,T) dis[i]=INF;
    	static queue <int> que;
    	dis[S]=0; que.push(S);
    	while(!que.empty()) {
    		int u=que.front(); que.pop();
    		for(int i=head[u];i;i=e[i].nxt) {
    			int v=e[i].to,w=e[i].w;
    			if(!w || dis[v]<=dis[u]+1) continue;
    			dis[v]=dis[u]+1,que.push(v);
    		}
    	}
    	return dis[T]<INF;
    }
    
    int Dfs(int u,int in) {
    	if(u==T) return in;
    	int out=0;
    	for(int i=head[u];i;i=e[i].nxt) {
    		int v=e[i].to,w=e[i].w;
    		if(!w || dis[v]!=dis[u]+1) continue;
    		int t=Dfs(v,min(in-out,w));
    		e[i].w-=t,e[i^1].w+=t,out+=t;
    		if(in==out) break;
    	}
    	if(!out) dis[u]=0;
    	return out;
    }
    
    int Dinic() {
    	int ans=0; 
    	while(Bfs()) ans+=Dfs(S,INF);
    	return ans;
    }
    
    
    int main() {
    	rep(kase,1,rd()) {
    		n=rd(),m=rd();
    		rep(i,1,n) F[i]=i,col[i]=0;
    		scanf("%s",s+1);
    		S=n+1,T=n+2;
    		rep(i,1,n) A[i]=rd();
    		rep(i,1,m) {
    			X[i]=rd(),Y[i]=rd();
    			int x=abs(X[i]),y=abs(Y[i]);
    			int u=Find(x),v=Find(y);
    			if(u==v) continue;
    			F[u]=v,col[u]=col[x]^col[y]^(X[i]<0)^(Y[i]<0)^1;
    		}
    		rep(i,1,n) Find(i);
    		rep(i,1,n) {
    			if(col[i]^s[i]^'0') Link(S,i,A[i]);
    			else Link(i,T,A[i]);
    		}
    		rep(i,1,m) {
    			int t=col[abs(X[i])]^(X[i]<0);
    			assert(col[abs(X[i])]^col[abs(Y[i])]^(X[i]<0)^(Y[i]<0));
    			if(t) Link(abs(X[i]),abs(Y[i]),INF);
    			else Link(abs(Y[i]),abs(X[i]),INF);
    		}
    		printf("%d
    ",Dinic());
    		rep(i,1,T) head[i]=0; ecnt=1;
    	}
    }
    
  • 相关阅读:
    设置元素等待.py
    javaWeb服务详解(含源代码,测试通过,注释)
    com.sun.istack.SAXException2: 在对象图中检测到循环。这将产生无限深的 XML
    com.sun.istack.SAXException2: 在对象图中检测到循环。这将产生无限深的 XML
    No services have been found解决方案
    No services have been found解决方案
    JavaMail给QQ邮箱发邮件报错,没有SSL加密
    JavaMail给QQ邮箱发邮件报错,没有SSL加密
    JavaMail给QQ邮箱发邮件报错
    JavaMail给QQ邮箱发邮件报错
  • 原文地址:https://www.cnblogs.com/chasedeath/p/13995731.html
Copyright © 2020-2023  润新知