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;
    }
    
  • 相关阅读:
    log4j1修改DailyRollingFileAppender支持日志最大数量
    log4j1 修改FileAppender解决当天的文件没有日期后缀
    log4j生成有日期的日志文件名
    Java删除List和Set集合中元素
    Java并发编程:并发容器之ConcurrentHashMap
    Java并发编程:并发容器之CopyOnWriteArrayList
    java.util.ConcurrentModificationException解决详解
    Handshake failed due to invalid Upgrade header: null 解决方案
    web项目Log4j日志输出路径配置问题
    log4j.properties 的使用详解
  • 原文地址:https://www.cnblogs.com/Mychael/p/12268902.html
Copyright © 2011-2022 走看看