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

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

最后做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. 计算几何基础算法几何C++实现

    This file is implementation of Common Common Computational Geometry Algorithms.Please please pay att ...

  2. 解决Mac安装tesserocr报错问题 Failed building wheel for

    localhost:~ jerry$ Processing /var/www/git/python/tesserocr -bash: Processing: command not found loc ...

  3. unittest生成测试报告

    1.先导入HTMLTestRunner模块 2.实例一脚本如下 #coding=utf-8 import unittest import HTMLTestRunner #封装批量执行用例 def al ...

  4. Mac下载魔兽世界怀旧服客户端 for Mac

    <魔兽世界>怀旧服2019年8月9日凌晨2点开启全球压力测试,并将于8月27日正式开服.<魔兽世界>十五年,青春有它否?不见的战友,难抹的回忆,说不出口的遗憾?来,让我们一起回 ...

  5. PHP ksort

    1.例子一: <?php /** * 根据 c1 对元素排序 */ $arrays = [ 'b' => [ 'c1' => 10, 'c2' => 5, ], 'a' =&g ...

  6. 第三篇-分析日志和sensor-data中的数据结构

    分析日志和sensor-data数据结构 该文章提供web端思路,ios和android端思路不提供,api也已经下线,本文也不提供任何可执行代码.有更多疑问欢迎查看github代码 协议 授权协议: ...

  7. 使用eclipse在tomcat中设置项目启动的虚拟路径

    很多时候我们在启动项目的时候都会在浏览器输入"localhost:+端口号+项目名称" 其实tomcat是可以省去这种麻烦的,通过设置项目的虚拟路径就可访问项目了 第一步 选择ec ...

  8. beanfactory中单例bean的初始化过程(一)

    Date 10.06 pm Point 完成beanfactory中单例bean的初始化 beanFactory.preInstantiateSingletons() 拿到所有的bean定义信息(在 ...

  9. 有些需要禁用的PHP危险函数(disable_functions)

    phpinfo() 功能描述:输出 PHP 环境信息以及相关的模块.WEB 环境等信息. 危险等级:中 passthru() 功能描述:允许执行一个外部程序并回显输出,类似于 exec(). 危险等级 ...

  10. requests+lxml+xpath爬取豆瓣电影

    (1)lxml解析html from lxml import etree #创建一个html对象 html=stree.HTML(text) result=etree.tostring(html,en ...