zoukankan      html  css  js  c++  java
  • cf1242C Sum Balance 【图 + 状压】

    题目链接

    cf1242C

    题解

    题意:有K个组,每组有若干个数【所有数互异】,现在从每个组取出一个数,然后再将这些数分别放入一个组中,是否存在方案使得操作结束后每个组数字的和相等

    最后相等的和是固定的,我们可以求出每个组距离结果的差值,对于这个组每个数,如果要将其取出,那么放入的一定就是这个数再减去这个差值的数值,而所有数互异,这样的值最多一个。这样每个数都可以找到一个这样匹配的数,向其连边,这样这张图中一个环就代表了一个轮换。如果我们能找到一组环,使得每个组都被包含一次,那么就是答案。
    由于每个点只连出一条边,只可能形成简单环,dfs就能将其找出
    最后每个环用二进制表示状态进行状压dp,即可得到结果。

    #include<algorithm>
    #include<iostream>
    #include<cstdlib>
    #include<cstring>
    #include<cstdio>
    #include<vector>
    #include<queue>
    #include<cmath>
    #include<map>
    #define LL long long int
    #define REP(i,n) for (int i = 1; i <= (n); i++)
    #define Redge(u) for (int k = h[u],to; k; k = ed[k].nxt)
    #define cls(s,v) memset(s,v,sizeof(s))
    #define mp(a,b) make_pair<int,int>(a,b)
    #define cp pair<int,int>
    using namespace std;
    const int maxn = 100005,maxm = (1 << 15),INF = 0x3f3f3f3f;
    inline int read(){
    	int out = 0,flag = 1; char c = getchar();
    	while (c < 48 || c > 57){if (c == '-') flag = 0; c = getchar();}
    	while (c >= 48 && c <= 57){out = (out << 1) + (out << 3) + c - 48; c = getchar();}
    	return flag ? out : -out;
    }
    struct node{
    	LL v,id;
    }A[maxn];
    inline bool operator < (const node& a,const node& b){
    	return a.v < b.v;
    }
    LL K,n,nxt[maxn];
    LL sum,av,S[20],Lack[20];
    LL vis[maxn],cnt;
    LL s[maxn],ent[maxn],si;
    int vv[20];
    void dfs(int u){
    	vis[u] = cnt;
    	if (!nxt[u]) return;
    	if (!vis[nxt[u]]) dfs(nxt[u]);
    	else if (vis[nxt[u]] == cnt){
    		for (int i = 1; i <= K; i++) vv[i] = 0;
    		vv[A[u].id] = true;
    		for (int t = nxt[u]; t != u; t = nxt[t]){
    			if (vv[A[t].id]) return;
    			vv[A[t].id] = true;
    		}
    		s[++si] = (1 << (A[u].id - 1));
    		ent[si] = u;
    		for (int t = nxt[u]; t != u; t = nxt[t]){
    			s[si] |= (1 << (A[t].id - 1));
    		}
    	}
    }
    void getc(){
    	sort(A + 1,A + 1 + n);
    	for (int i = 1; i <= n; i++){
    		if (!Lack[A[i].id]) continue;
    		LL x = A[i].v - Lack[A[i].id],pos = lower_bound(A + 1,A + 1 + n,(node){x,0}) - A;
    		if (pos >= 1 && pos <= n && A[pos].v == x && A[pos].id != A[i].id && Lack[A[pos].id])
    			nxt[i] = pos;
    	}
    	for (int i = 1; i <= n; i++) if (!vis[i]) ++cnt,dfs(i);
    }
    LL f[maxm],pre[maxm],used[maxm];
    LL bi;
    struct Node{
    	LL id,v,to;
    }B[100];
    inline bool operator < (const Node& a,const Node& b){
    	return a.id < b.id;
    }
    void dp(){
    	int ini = 0;
    	for (int i = 1; i <= K; i++) if (!Lack[i]) ini |= (1 << (i - 1));
    	f[ini] = 1;
    	for (int i = 0; i <= (1 << K) - 1; i++){
    		if (!f[i]) continue;
    		for (int j = 1; j <= si; j++) if (!(i & s[j])){
    			int to = (i | s[j]);
    			f[to] = 1;
    			pre[to] = i;
    			used[to] = j;
    		}
    	}
    	int maxv = (1 << K) - 1;
    	if (!f[maxv]) puts("No");
    	else {
    		puts("Yes");
    		for (int i = maxv; i != ini; i = pre[i]){
    			int j = used[i],u = ent[j];
    			B[++bi] = (Node){A[nxt[u]].id,A[nxt[u]].v,A[u].id};
    			for (int v = nxt[u]; v != u; v = nxt[v]){
    				B[++bi] = (Node){A[nxt[v]].id,A[nxt[v]].v,A[v].id};
    			}
    		}
    		for (int i = 1; i <= K; i++) if (!Lack[i]){
    			for (int j = 1; j <= n; j++) if (A[j].id == i){
    				B[++bi] = (Node){i,A[j].v,i};
    				break;
    			}
    		}
    		sort(B + 1,B + 1 + bi);
    		for (int i = 1; i <= bi; i++) printf("%I64d %I64d
    ",B[i].v,B[i].to);
    	}
    }
    void work(){
    	getc();
    	dp();
    }
    int main(){
    	K = read();
    	for (int i = 1; i <= K; i++){
    		int m = read();
    		while (m--) A[++n].v = read(),A[n].id = i,sum += A[n].v,S[i] += A[n].v;
    	}
    	if (sum % K){puts("No"); return 0;}
    	av = sum / K;
    	REP(i,K) Lack[i] = S[i] - av;
    	work();
    	return 0;
    }
    
  • 相关阅读:
    高斯消元学习
    HDU 4596 Yet another end of the world(解一阶不定方程)
    Codeforces Round #318 div2
    HDU 4463 Outlets(一条边固定的最小生成树)
    HDU 4458 Shoot the Airplane(计算几何 判断点是否在n边形内)
    HDU 4112 Break the Chocolate(简单的数学推导)
    HDU 4111 Alice and Bob (博弈)
    POJ 2481 Cows(线段树单点更新)
    HDU 4288 Coder(STL水过)
    zoj 2563 Long Dominoes
  • 原文地址:https://www.cnblogs.com/Mychael/p/12268902.html
Copyright © 2011-2022 走看看