这题写起来真的有点麻烦,按照官方题解的写法

先建图,然后求强连通分量,然后判断掉不符合条件的换

最后做dp转移即可

虽然看起来复杂度很高,但是n只有15,所以问题不大

#include <iostream>
#include <fstream>
#include <vector>
#include <set>
#include <map>
#include <bitset>
#include <algorithm>
#include <iomanip>
#include <cmath>
#include <ctime>
#include <functional>
#include <unordered_set>
#include <unordered_map>
#include <queue>
#include <deque>
#include <stack>
#include <complex>
#include <cassert>
#include <random>
#include <cstring>
#include <numeric>
#define ll long long
#define ld long double
#define null NULL
#define all(a) a.begin(), a.end()
#define forn(i, n) for (int i = 0; i < n; ++i)
#define sz(a) (int)a.size()
#define lson l , m , rt << 1
#define rson m + 1 , r , rt << 1 | 1
#define bitCount(a) __builtin_popcount(a)
template<class T> int gmax(T &a, T b) { if (b > a) { a = b; return 1; } return 0; }
template<class T> int gmin(T &a, T b) { if (b < a) { a = b; return 1; } return 0; }
using namespace std;
string to_string(string s) { return '"' + s + '"'; }
string to_string(const char* s) { return to_string((string) s); }
string to_string(bool b) { return (b ? "true" : "false"); }
template <typename A, typename B>
string to_string(pair<A, B> p) { return "(" + to_string(p.first) + ", " + to_string(p.second) + ")"; }
template <typename A>
string to_string(A v) { bool first = true; string res = "{"; for (const auto &x : v) { if (!first) { res += ", "; } first = false; res += to_string(x); } res += "}"; return res; }
void debug_out() { cerr << endl; }
template <typename Head, typename... Tail>
void debug_out(Head H, Tail... T) { cerr << " " << to_string(H); debug_out(T...); }
#ifdef LOCAL
#define debug(...) cerr << "[" << #__VA_ARGS__ << "]:", debug_out(__VA_ARGS__)
#else
#define debug(...) 42
#endif const int MAXN = 75005;
vector<int> graph[MAXN];
vector<int> group[MAXN];
int dfn[MAXN], low[MAXN];
int dcnt;
int col[MAXN + 5], ccnt;
bool vis[MAXN + 5];
int stk[MAXN + 5], tp;
vector<pair<int, int>> dp[32768]; void Tarjan_scc(int u) {
dfn[u] = ++dcnt, low[u] = dcnt, vis[u] = true;
stk[++tp] = u;
for(int i = 0; i < (int)graph[u].size(); i++) {
int v = graph[u][i];
if(!dfn[v]) {
Tarjan_scc(v);
low[u] = min(low[u], low[v]);
} else if(vis[v]) low[u] = min(low[u], low[v]);
}
if(dfn[u] == low[u]) {
++ccnt;
while(true) {
col[stk[tp]] = ccnt;
vis[stk[tp]] = false;
if(stk[tp--] == u)
break;
}
}
} int main() {
int k;
while(~scanf("%d", &k)) {
tp = -1; ccnt = 0; dcnt = 0;
for(int i = 0; i < MAXN; ++i) {
dfn[i] = 0;
graph[i].clear();
group[i].clear();
} vector<ll> sum;
vector<pair<int, int> > vc;
map<ll, pair<int, int> > mp; int tot = 0;
ll allSum = 0;
for(int i = 0; i < k; ++i) {
int x; scanf("%d", &x);
ll tmpSum = 0;
for(int j = 0; j < x; ++j) {
int y; scanf("%d", &y);
vc.push_back(make_pair(y, i));
mp[y] = make_pair(tot, i);
tot ++;
tmpSum += y;
}
sum.push_back(tmpSum);
allSum += tmpSum;
}
// debug(allSum); if(allSum % k) {
printf("No\n");
continue;
} allSum /= k;
set<int> selfCircle;
set<pair<int, int>> hasEdge; // debug(allSum);
for(int i = 0, len = vc.size(); i < len; ++i) {
ll searchNum = allSum - sum[vc[i].second] + vc[i].first;
if(mp.find(searchNum) == mp.end()) continue;
else if( mp[searchNum].second == vc[i].second && mp[searchNum].first != i) {
// solve specfial condition
continue;
} else if(mp[searchNum].first == i) {
// debug(i);
selfCircle.insert(i);
} graph[i].push_back(mp[searchNum].first);
hasEdge.insert(make_pair(i, mp[searchNum].first)); debug(i, mp[searchNum].first);
} for(int i = 0; i < tot; ++i) {
if(!dfn[i]) Tarjan_scc(i);
} for(int i = 0; i < tot; ++i) {
// printf("%d ", col[i]);
group[col[i]].push_back(i);
}
// printf("\n"); for(int i = 1; i <= ccnt; ++i) {
// debug(i, group[i].size());
if(group[i].size() == 1 && selfCircle.count(group[i][0])) {
int id = group[i][0];
vector<pair<int, int> > tmpPair;
tmpPair.push_back(make_pair(vc[id].first, vc[id].second + 1));
dp[1<<vc[id].second] = tmpPair;
// debug(dp[1<<vc[id].second]);
}
else if(group[i].size() > 1) {
vector<pair<int, int> > tmpPair;
int tmp = 0;
int len = group[i].size();
bool suc = true;
for(int j = 0; j < len; ++j) {
int to = group[i][j];
if(tmp & (1<<vc[to].second)) { suc = false; break; }
tmp |= 1<<vc[to].second;
}
if(suc == false) {
continue;
} for(int j = 0; j < len; ++j) {
for(int k = 0; k < len; ++k) {
int fr = group[i][j]; int to = group[i][k];
if(hasEdge.count(make_pair(fr, to))) {
tmpPair.push_back(make_pair(vc[to].first, vc[fr].second + 1));
}
}
} dp[tmp] = tmpPair;
// debug(dp[tmp], tmp);
}
} for(int i = 0; i < (1<<k); ++i) {
for (int s=(i-1)&i; s; s=(s-1)&i) {
int t = i ^ s;
if(dp[s].size() > 0 && dp[t].size() > 0) {
dp[i] = dp[s];
dp[i].insert(dp[i].end(), dp[t].begin(), dp[t].end());
break;
}
}
} auto cmp = [&](pair<int, int> &A, pair<int, int> &B) {
return mp[A.first].second < mp[B.first].second;
}; int end = (1<<k) - 1;
if(dp[end].size() > 0 ) {
printf("Yes\n");
// debug(dp[end]);
sort(dp[end].begin(), dp[end].end(), cmp);
for(int i = 0; i < k; ++i) {
printf("%d %d\n", dp[end][i].first, dp[end][i].second);
}
} else printf("No\n"); }
return 0;
}

Codeforces Round #599 (Div. 2) E. Sum Balance的更多相关文章

  1. Codeforces Round #599 (Div. 1) C. Sum Balance 图论 dp

    C. Sum Balance Ujan has a lot of numbers in his boxes. He likes order and balance, so he decided to ...

  2. Codeforces Round #599 (Div. 2) D. 0-1 MST(bfs+set)

    Codeforces Round #599 (Div. 2) D. 0-1 MST Description Ujan has a lot of useless stuff in his drawers ...

  3. Codeforces Round #530 (Div. 2):D. Sum in the tree (题解)

    D. Sum in the tree 题目链接:https://codeforces.com/contest/1099/problem/D 题意: 给出一棵树,以及每个点的si,这里的si代表从i号结 ...

  4. Codeforces Round #599 (Div. 2)

    久违的写篇博客吧 A. Maximum Square 题目链接:https://codeforces.com/contest/1243/problem/A 题意: 给定n个栅栏,对这n个栅栏进行任意排 ...

  5. Codeforces Round #599 (Div. 2) A,B1,B2,C 【待补 D】

    排序+暴力 #include<bits/stdc++.h> using namespace std; #define int long long #define N 1005000 int ...

  6. Codeforces Round #530 (Div. 2) D. Sum in the tree 树上贪心

    D. Sum in the tree 题意 给出一颗树,奇数层数的点有值,值代表从1到该点的简单路的权值的和,偶数层数的点权值被擦去了 问所有节点的和的最小可能是多少 思路 对于每一个-1(也就是值未 ...

  7. Codeforces Round #599 (Div. 2) B1. Character Swap (Easy Version)

    This problem is different from the hard version. In this version Ujan makes exactly one exchange. Yo ...

  8. Codeforces Round #599 (Div. 2)D 边很多的只有0和1的MST

    题:https://codeforces.com/contest/1243/problem/D 分析:找全部可以用边权为0的点连起来的全部块 然后这些块之间相连肯定得通过边权为1的边进行连接 所以答案 ...

  9. Codeforces Round #530 (Div. 1) 1098A Sum in the tree

    A. Sum in the tree Mitya has a rooted tree with nn vertices indexed from 11 to nn, where the root ha ...

随机推荐

  1. 网页布局——Flex弹性框布局

    布局的传统解决方案,基于盒状模型,依赖 display 属性 + position属性 + float属性.它对于那些特殊布局非常不方便,比如,垂直居中就不容易实现. 需要安卓4.4及以上版本可以使用 ...

  2. 关于Qt画点及计算机专业基础课程介绍

    在计算机图形图像学中,开始都是先画点,我曾经在汇编上tc2.0上画点,后来是MFC,VB,Qt,Python,我觉得对于计算机专业的选择QT的原因是它是个C系的功能强大庞大的库,可以少写很多代码,但是 ...

  3. web前端Vue+Django rest framework 框架 生鲜电商项目实战视频教程 ☝☝☝

    web前端Vue+Django rest framework 框架 生鲜电商项目实战视频教程    web前端Vue+Django rest framework 框架 生鲜电商项目实战视频教程 学习 ...

  4. vue-cli中使用jquery

    一.安装依赖 npm install jquery --save 二.全局导入(必须先安装依赖) 第一步 在webpack.base.conf.js里加入(新版的可能找不到这个文件,你可以npm in ...

  5. SpringBoot系列:Spring Boot集成Spring Cache,使用RedisCache

    前面的章节,讲解了Spring Boot集成Spring Cache,Spring Cache已经完成了多种Cache的实现,包括EhCache.RedisCache.ConcurrentMapCac ...

  6. moloch1.8.0简单操作手册

    moloch1.8.0简单操作手册 Sessions 页面:Sessions主要通过非常简单的查询语言来构建表达式追溯数据流量,以便分析. SPIView 页面: SPIGraph页面:SPIGrap ...

  7. dos命令创建批处理脚本

    win+r  打开cmd 输入 copy con  1.bat 回车 进入编辑状态输入 @echo off echo xxxx Ctrl+z 结束编辑   会在当前目录生成一个bat文件

  8. MySQL 分页查询优化——延迟关联优化

    目录 1.   InnoDB表的索引的几个概念 2.   覆盖索引和回表 3.   分页查询 4.   延迟关联优化 写在前面 下面的介绍均是在选用MySQL数据库和Innodb引擎的基础开展.我们先 ...

  9. Mybaits 源码解析 (一)----- 搭建一个mybatis框架(MyBatis HelloWorld)

    源码分析之前先搭一个mybatis的demo,这个在看源码的时候能起到了很大的作用,因为在看源码的时候,会恍然大悟,为什么要这么配置,为什么要这么写.(老鸟可以跳过这篇) 开发环境的准备 创建mave ...

  10. python问题:IndentationError:expected an indented block

    Python语言是一款对缩进非常敏感的语言,给很多初学者带来了困惑,即便是很有经验的Python程序员,也可能陷入陷阱当中.最常见的情况是tab和空格的混用会导致错误,或者缩进不对,而这是用肉眼无法分 ...