题目

有 \(k\) 个盒子, 第 \(i\) 个盒子有 \(n_i\) 个数. 保证所有数互不相同。

从每个盒子各拿出一个数, 并按照某种顺序放回去(每个盒子恰好放入一个数)。

判断是否能使操作后所有盒子内的数的和相同, 有解需要输出任意一个方案。

\(k\leq 15,n_i\leq 5000\)


分析

可以发现拿出一个数,那么放进去的这个数也是确定的,那么这样就确定的有向的关系。

由于每个点只往外连一条边,所以这张有向图实则形成一个内向基环树。

相当于要将所有的环抽出来,可以作为一种子方案,然后再将所有环拼接起来,相当于枚举子集。

时间复杂度为 \(O(3^k+2^k*k)\)

可以先跑一遍拓扑排序将非环的部分剔除掉,然后只找环的部分,注意如果环内存在两个数在同一盒子且并不相同,那么这个环不能使用。


代码

#include <cstdio>
#include <cctype>
#include <queue>
#include <vector>
#include <map>
#include <algorithm>
using namespace std;
const int N=80101; vector<int>ans[N]; map<long long,int>dfn; queue<int>q;
int xo[N],deg[N],nxt[N],v[N],n,al,a[16][N>>4],S,tot,X[N],Y[N],pre[N]; long long s[16],sum;
int iut(){
int ans=0,f=1; char c=getchar();
while (!isdigit(c)) f=(c=='-')?-f:f,c=getchar();
while (isdigit(c)) ans=ans*10+c-48,c=getchar();
return ans*f;
}
int main(){
n=iut(),al=(1<<n)-1;
for (int i=1;i<=al;++i) xo[i]=xo[i&(i-1)]+1;
for (int i=1;i<=n;++i){
a[i][0]=iut();
for (int j=1;j<=a[i][0];++j){
a[i][j]=iut(),s[i]+=a[i][j];
dfn[a[i][j]]=++tot;
X[tot]=i,Y[tot]=j;
}
sum+=s[i];
}
if (sum%n) return !printf("No");
sum/=n;
for (int i=1;i<=n;++i){
for (int j=1;j<=a[i][0];++j)
if (dfn.count(sum-(s[i]-a[i][j]))){
int x=dfn[a[i][j]],y=dfn[sum-(s[i]-a[i][j])];
if (X[x]==X[y]&&Y[x]!=Y[y]) continue;
nxt[x]=y,++deg[y];
}
}
for (int i=1;i<=tot;++i) if (!deg[i]) q.push(i);
while (!q.empty()){
int x=q.front(); q.pop();
if (nxt[x]&&!(--deg[nxt[x]])) q.push(nxt[x]);
}
for (int i=1,flag;i<=tot;++i)
if (deg[i]&&!v[i]){
S=1<<(X[i]-1),flag=v[i]=1,pre[nxt[i]]=i;
for (int x=nxt[i];x!=i;x=nxt[x]){
if ((S>>(X[x]-1))&1) flag=0;
pre[nxt[x]]=x,v[x]=1,S|=1<<(X[x]-1);
}
if (!flag||!ans[S].empty()) continue;
ans[S].push_back(i);
for (int x=nxt[i];x!=i;x=nxt[x]) ans[S].push_back(x);
}
for (int i=1;i<=al;++i)
if (ans[i].empty()){
for (int j=i&(i-1);j;j=(j-1)&i)
if (!ans[j].empty()&&!ans[i^j].empty()){
ans[i]=ans[i^j];
for (int k=0;k<xo[j];++k)
ans[i].push_back(ans[j][k]);
}
}
if (ans[al].empty()) return !printf("No");
sort(ans[al].begin(),ans[al].end());
printf("Yes\n");
for (int i=0;i<n;++i){
int now=ans[al][i];
printf("%d %d\n",a[X[now]][Y[now]],X[pre[now]]);
}
return 0;
}

#状压dp,拓扑排序,内向基环树#CF1242C Sum Balance的更多相关文章

  1. 【BZOJ 2595】2595: [Wc2008]游览计划 (状压DP+spfa,斯坦纳树?)

    2595: [Wc2008]游览计划 Time Limit: 10 Sec  Memory Limit: 256 MBSec  Special JudgeSubmit: 1572  Solved: 7 ...

  2. 【XSY3042】石像 拓扑排序 状压DP 洲阁筛

    题目大意 有 \(n\) 个整数 \(a_1,a_2,\ldots,a_n\),每个数的范围是 \([1,m]\).还有 \(k\) 个限制,每个限制 \(x_i,y_i\) 表示 \(a_{x_i} ...

  3. HDU 4917 Permutation(拓扑排序 + 状压DP + 组合数)

    题目链接 Permutation 题目大意:给出n,和m个关系,每个关系为ai必须排在bi的前面,求符合要求的n的全排列的个数. 数据规模为n <= 40,m <= 20. 直接状压DP空 ...

  4. 【62测试】【状压dp】【dfs序】【线段树】

    第一题: 给出一个长度不超过100只包含'B'和'R'的字符串,将其无限重复下去. 比如,BBRB则会形成 BBRBBBRBBBRB 现在给出一个区间[l,r]询问该区间内有多少个字符'B'(区间下标 ...

  5. bzoj 4006 [JLOI2015]管道连接(斯坦纳树+状压DP)

    [题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=4006 [题意] 给定n点m边的图,连接边(u,v)需要花费w,问满足使k个点中同颜色的 ...

  6. 51nod 1673 树有几多愁——虚树+状压DP

    题目:http://www.51nod.com/Challenge/Problem.html#!#problemId=1673 建一个虚树. 一种贪心的想法是把较小的值填到叶子上,这样一个小值限制到的 ...

  7. bzoj1402 Ticket to Ride 斯坦纳树 + 状压dp

    给定\(n\)个点,\(m\)条边的带权无向图 选出一些边,使得\(4\)对点之间可达,询问权值最小为多少 \(n \leqslant 30, m \leqslant 1000\) 首先看数据范围,\ ...

  8. 【bzoj4006】[JLOI2015]管道连接 斯坦纳树+状压dp

    题目描述 给出一张 $n$ 个点 $m$ 条边的无向图和 $p$ 个特殊点,每个特殊点有一个颜色.要求选出若干条边,使得颜色相同的特殊点在同一个连通块内.输出最小边权和. 输入 第一行包含三个整数 n ...

  9. BZOJ2595 Wc2008 游览计划 【斯坦纳树】【状压DP】*

    BZOJ2595 Wc2008 游览计划 Description Input 第一行有两个整数,N和 M,描述方块的数目. 接下来 N行, 每行有 M 个非负整数, 如果该整数为 0, 则该方块为一个 ...

  10. luogu4294 [WC2008]游览计划(状压DP/斯坦纳树)

    link 题目大意:给定一个网格图,有些点是关键点,选择格点有代价,求把所有关键点联通的最小代价 斯坦纳树模板题 斯坦纳树问题:给定一个图结构,有一些点是关键点,求把这些关键点联通的最小代价e 斯坦纳 ...

随机推荐

  1. win32-创建一个屏幕准星(UpdateLayeredWindow)

    // Test_1.cpp : Defines the entry point for the application. // #include "framework.h" #in ...

  2. 【LeetCode二叉树#16】二叉(搜索)树的最近公共祖先(递归后序遍历,巩固回溯机制)

    二叉树的最近公共祖先 力扣题目链接(opens new window) 给定一个二叉树, 找到该树中两个指定节点的最近公共祖先. 百度百科中最近公共祖先的定义为:"对于有根树 T 的两个结点 ...

  3. 【Azure 应用服务】收集App Service 关于Availability Zone, Health check 以及 Traffic Manager的文档,并了解高可用(HA)和灾备(DR)

    问题描述 收集App Service 关于Availability Zone, Health check 以及 Traffic Manager的文档,并了解高可用(HA)和灾备(DR)的具体办法 问题 ...

  4. 【Azure 应用服务】如何定期自动重启 Azure App Service Plan(应用服务计划)

    问题描述 如何定期自动重启 Azure App Service Plan(应用服务计划)? 因一个App Service Plan 下包含多个应用服务,如果能统一通过应用服务计划来重启所有的应用,则有 ...

  5. Zabbix MQQT协议监控 loT设备

    一. 项目背景 监控异地局域网主机(主机内有物联5G卡 可以单方面向特定的云服务器传输信息)这里采用 zabbix 5xx系列 agent2 -6.2 版本 主动模式,即客户端向服务端注册.   二. ...

  6. 聊聊CWE 4.14 与 ISA/IEC 62443中,如何保障工业软件的安全性

    本文分享自华为云社区<CWE 4.14 与 ISA/IEC 62443>,作者:Uncle_Tom. 1. 序言 随着 5G 的应用,物联的网发展,越来越多的自动化控制系统.云服务在工业控 ...

  7. git 全局用户名改为英文,中文生成的git记录文件 不能有中文,现场反馈 git config user.name

    设置用户名和邮箱 git config --global user.name "username" git config --global user.email useremail ...

  8. ECharts 中国地图 vue

    <template> <div> <div id="china_map_box"> <div id="china_map&quo ...

  9. C#实现软件开机自启动(不需要管理员权限)

    目录 原理简介 使用方法 完整代码 原理简介 本文参考C#/WPF/WinForm/程序实现软件开机自动启动的两种常用方法,将里面中的第一种方法做了封装成AutoStart类,使用时直接两三行代码就可 ...

  10. C++ bind函数

    bind()是一个函数适配器,返回一个可调用对象,他可以将一个函数的参数列表做魔改. 设置默认参数 using namespace std::placeholders; void f(int a, i ...