zoukankan      html  css  js  c++  java
  • CF1290C Prefix Enlightenment (并查集)

    大意: 给定长$n$的01串$s$, 给定$k$个集合$A_1,...,A_k$,保证任意三个集合交集为空. 每次操作选择一个集合,翻转$s$中对应位置. 定义$m_i$为使前$i$个位置全为$1$所需的最少操作数(题目数据保证每个$m_i$都存在), 求所有$m_i$的值.

    显然每个位置最多属于两个集合.

    假设只对应一个集合$X$, 那么$X=overline{s_i}$

    假设对应集合$X,Y$, 那么$Xoplus Y=overline{s_i}$

    所以题目就等价于给定一些异或方程组, 求最少多少个变量值为1.

    考虑把每个集合拆成两个点$X_1,X_0$表示选或不选. 

    对于$Xoplus Y=1$, 就连边$(X_1,Y_0),(X_0,Y_1)$

    对于$Xoplus Y=0$, 就连边$(X_1,Y_1),(X_0,Y_0)$

    对于$X=overline{s_i}$, 有一个技巧是设一个权值无穷大的点, 限制$X$不能选$s_i$.

    可以用并查集实现, 选一个权值和最小的连通块即可. 

    #include <iostream>
    #include <algorithm>
    #include <cstdio>
    #include <vector>
    #define REP(_i,_a,_n) for(int _i=_a;_i<=_n;++_i)
    #define PER(_i,_a,_n) for(int _i=_n;_i>=_a;--_i)
    #define pb push_back
    using namespace std;
    typedef long long ll;
    typedef pair<int,int> pii;
    const int P = 1e9+7, INF = 0x3f3f3f3f;
    const int N = 1e6+10;
    int n, k, fa[N], val[N];
    char s[N];
    vector<int> g[N];
    int Find(int x) {return fa[x]?fa[x]=Find(fa[x]):x;}
    void add(int x, int y) {
    	x = Find(x), y = Find(y);
    	if (x!=y) fa[x]=y,val[y]+=val[x];
    }
    int calc(int x) {
    	return min(val[Find(x)],val[Find(x+k)]);
    }
    
    int main() {
    	scanf("%d%d%s",&n,&k,s+1);
    	REP(i,1,k) {
    		int x, t;
    		scanf("%d",&x);
    		while (x--) {
    			scanf("%d", &t);
    			g[t].pb(i);
    		}
    	}
    	REP(i,k+1,2*k) val[i] = 1;
    	val[2*k+1] = INF;
    	int ans = 0;
    	REP(i,1,n) {
    		if (g[i].size()==1) {
    			ans -= calc(g[i][0]);
    			if (s[i]=='1') add(g[i][0]+k,2*k+1);
    			else add(g[i][0],2*k+1);
    			ans += calc(g[i][0]);
    		}
    		else if (g[i].size()==2) {
    			int x = g[i][0], y = g[i][1];
    			if (Find(x)!=Find(y)&&Find(x)!=Find(y+k)) {
    				ans -= calc(x)+calc(y);
    				if (s[i]=='1') add(x,y),add(x+k,y+k);
    				else add(x+k,y),add(x,y+k);
    				ans += calc(x);
    			}
    		}
    		printf("%d
    ", ans);
    	}
    }
    
  • 相关阅读:
    二级指针与二维数组
    二维数组的两种访问方式
    函数返回局部变量
    函数指针
    链表
    二叉树各种遍历
    二叉树常见问题
    C语言单链表实现19个功能完全详解
    halcon算子翻译——set_fuzzy_measure_norm_pair
    Halcon算子翻译——set_fuzzy_measure
  • 原文地址:https://www.cnblogs.com/uid001/p/12272628.html
Copyright © 2011-2022 走看看