码迷,mamicode.com
首页 > 其他好文 > 详细

cf1242C Sum Balance 【图 + 状压】

时间:2020-02-06 16:30:47      阅读:98      评论:0      收藏:0      [点我收藏+]

标签:lower   简单   题意   def   固定   sed   node   else   个数   

题目链接

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\n",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;
}

cf1242C Sum Balance 【图 + 状压】

标签:lower   简单   题意   def   固定   sed   node   else   个数   

原文地址:https://www.cnblogs.com/Mychael/p/12268902.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!