topcoder srm 630 div1 (2-SAT and SCC template)
problem1 link
首先计算任意两点的距离。然后枚举选出的集合中的两个点,判断其他点是否可以即可。
problem2 link
假设字符串为$s$,长度为$n$。那么对于$SA$中的两个排名$SA_{i},SA_{i+1}$来说,应该尽量使得$s[SA_{i}]=s[SA_{i+1}]$。如果这个满足的话,那么需要两个后缀满足$s[SA_{i}+1\sim n-1]<s[SA_{i+1}+1\sim n-1]$,设他们的排名分别为$SA_{r},SA_{k}$,也就是说$r<k$即可。
problem3 link
这个可以转化为2-SAT问题。
首先将每个点拆成202个点,分别表示$\leq 0,\leq 1,...,\leq 100,>0,>1,...,>100$.然后就是每一个等式可以转化为一些2-SAT中的限制。
比如对于$g_{x}+g_{y}<50$来说.比如$g_{x}> 19,g_{y}> 29$是冲突的,那么在2-SAT可以描述为$g_{x}> 19\rightarrow g_{y}\leq 29$,以及$g_{y}> 29\rightarrow g_{x}\leq 19$
最后就是得到2_SAT的一组解。
code for problem1
#include <algorithm>
#include <unordered_set>
#include <vector> class Egalitarianism3 {
public:
int maxCities(int n, const std::vector<int> &a, const std::vector<int> &b,
const std::vector<int> &len) {
if (n == 1) {
return 1;
}
std::vector<std::vector<int>> g(n, std::vector<int>(n, -1));
for (int i = 0; i < n - 1; ++i) {
g[a[i] - 1][b[i] - 1] = g[b[i] - 1][a[i] - 1] = len[i];
}
for (int i = 0; i < n; ++i) {
g[i][i] = 0;
}
for (int i = 0; i < n; ++i) {
for (int u = 0; u < n; ++u) {
if (g[u][i] != -1) {
for (int v = 0; v < n; ++v) {
if (g[i][v] != -1) {
if (g[u][v] == -1 || g[u][v] > g[u][i] + g[i][v]) {
g[u][v] = g[u][i] + g[i][v];
}
}
}
}
}
}
auto Compute = [&](int s, int t) {
std::unordered_set<int> all;
all.insert(s);
all.insert(t);
const int d = g[s][t];
for (int i = 0; i < n; ++i) {
if (all.find(i) == all.end()) {
bool tag = true;
for (auto e : all) {
if (g[i][e] != d) {
tag = false;
break;
}
}
if (tag) {
all.insert(i);
}
}
}
return static_cast<int>(all.size());
};
int result = 0;
for (int i = 0; i < n; ++i) {
for (int j = i + 1; j < n; ++j) {
result = std::max(result, Compute(i, j));
}
}
return result;
}
};
code for problem2
#include <vector> class SuffixArrayDiv1 {
public:
int minimalCharacters(const std::vector<int> &SA) {
int n = static_cast<int>(SA.size());
std::vector<int> s(n + 1, -1);
for (int i = 0; i < n; ++i) {
s[SA[i]] = i;
}
int result = 1;
for (int i = 0; i + 1 < n; ++i) {
if (s[SA[i] + 1] > s[SA[i + 1] + 1]) {
++result;
}
}
return result;
}
};
code for problem3
#include <algorithm>
#include <stack>
#include <unordered_map>
#include <unordered_set>
#include <vector> class StronglyConnectedComponentSolver {
public:
StronglyConnectedComponentSolver() = default; void Initialize(int n) { edges_.resize(n); } std::vector<int> Solve() {
total_ = static_cast<int>(edges_.size());
if (total_ == 0) {
return {};
}
visited_.resize(total_, false);
low_indices_.resize(total_, 0);
dfs_indices_.resize(total_, 0);
connected_component_indices_.resize(total_, 0);
for (int i = 0; i < total_; ++i) {
if (0 == dfs_indices_[i]) {
Dfs(i);
}
}
return connected_component_indices_;
} int VertexNumber() const { return static_cast<int>(edges_.size()); } inline void AddEdge(int from, int to) { edges_[from].push_back(to); } const std::vector<int> &Tos(int u) const { return edges_[u]; } private:
void Dfs(const int u) {
low_indices_[u] = dfs_indices_[u] = ++index_;
stack_.push(u);
visited_[u] = true;
for (auto v : edges_[u]) {
if (0 == dfs_indices_[v]) {
Dfs(v);
low_indices_[u] = std::min(low_indices_[u], low_indices_[v]);
} else if (visited_[v]) {
low_indices_[u] = std::min(low_indices_[u], dfs_indices_[v]);
}
}
if (dfs_indices_[u] == low_indices_[u]) {
int v = 0;
do {
v = stack_.top();
stack_.pop();
visited_[v] = false;
connected_component_indices_[v] = connected_component_index_;
} while (u != v);
++connected_component_index_;
}
} std::vector<std::vector<int>> edges_;
int total_ = 0;
std::vector<bool> visited_;
std::vector<int> low_indices_;
std::vector<int> dfs_indices_;
std::stack<int> stack_;
int index_ = 0;
int connected_component_index_ = 0;
std::vector<int> connected_component_indices_;
}; class TwoSatisfiabilitySolver {
public:
void Initialize(int total_vertex_number) {
scc_solver_.Initialize(total_vertex_number);
} // If idx1 is type1, then idx2 must be type2.
void AddConstraint(int idx1, bool type1, int idx2, bool type2) {
int from = idx1 * 2 + (type1 ? 1 : 0);
int to = idx2 * 2 + (type2 ? 1 : 0);
scc_solver_.AddEdge(from, to);
} void AddConflict(int idx1, bool type1, int idx2, bool type2) {
AddConstraint(idx1, type1, idx2, !type2);
AddConstraint(idx2, type2, idx1, !type1);
} void AddLead(int idx1, bool type1, int idx2, bool type2) {
AddConstraint(idx1, type1, idx2, type2);
AddConstraint(idx2, !type2, idx1, !type1);
} // The idx must not be type
void SetFalse(int idx, bool type) { SetTrue(idx, !type); } // The idx must be type
void SetTrue(int idx, bool type) { AddConstraint(idx, !type, idx, type); } bool ExistSolution() {
if (scc_indices_.empty()) {
scc_indices_ = scc_solver_.Solve();
total_scc_number_ =
*std::max_element(scc_indices_.begin(), scc_indices_.end()) + 1;
}
for (int i = 0; i < scc_solver_.VertexNumber() / 2; ++i) {
if (scc_indices_[i * 2] == scc_indices_[i * 2 + 1]) {
return false;
}
}
return true;
} std::vector<bool> GetOneSolution() {
if (!ExistSolution()) {
return {};
}
BuildNewGraph();
TopSort();
int total = scc_solver_.VertexNumber();
std::vector<bool> result(total / 2);
for (int e = 0; e < total / 2; ++e) {
if (last_color_[scc_indices_[e * 2]] == 0) {
result[e] = false;
} else {
result[e] = true;
}
}
return std::move(result);
} private:
void BuildNewGraph() {
new_edges_.resize(total_scc_number_);
new_graph_node_in_degree_.resize(total_scc_number_, 0);
int total = scc_solver_.VertexNumber();
for (int i = 0; i < total; ++i) {
int scc0 = scc_indices_[i];
for (auto e : scc_solver_.Tos(i)) {
int scc1 = scc_indices_[e];
if (scc0 != scc1 &&
new_edges_[scc1].find(scc0) == new_edges_[scc1].end()) {
new_edges_[scc1].insert(scc0);
++new_graph_node_in_degree_[scc0];
}
}
}
} void TopSort() {
std::vector<int> conflict(total_scc_number_);
int total = scc_solver_.VertexNumber() / 2;
for (int i = 0; i < total; ++i) {
conflict[scc_indices_[i * 2]] = scc_indices_[i * 2 + 1];
conflict[scc_indices_[i * 2 + 1]] = scc_indices_[i * 2];
}
last_color_.resize(total_scc_number_, -1);
std::stack<int> st;
for (int i = 0; i < total_scc_number_; ++i) {
if (0 == new_graph_node_in_degree_[i]) {
st.push(i);
}
}
while (!st.empty()) {
int u = st.top();
st.pop();
if (last_color_[u] == -1) {
last_color_[u] = 0;
last_color_[conflict[u]] = 1;
}
for (auto e : new_edges_[u]) {
int cur = --new_graph_node_in_degree_[e];
if (cur == 0) {
st.push(e);
}
}
}
} std::vector<int> scc_indices_;
int total_scc_number_ = 0;
std::vector<std::unordered_set<int>> new_edges_;
std::vector<int> new_graph_node_in_degree_;
std::vector<int> last_color_; StronglyConnectedComponentSolver scc_solver_;
}; class NeverAskHerAge {
public:
std::vector<int> possibleSolution(int n, const std::vector<int> &id1,
const std::vector<int> &id2,
const std::vector<std::string> &op,
const std::vector<std::string> &rl,
const std::vector<int> &val) {
solver.Initialize(n * 101 * 2);
int m = static_cast<int>(id1.size());
// 0: <= j
// 1: > j
for (int i = 1; i <= n; ++i) {
for (int j = 0; j <= 100; ++j) {
if (j > 0) {
solver.AddLead(GetIndex(i, j), 1, GetIndex(i, j - 1), 1);
}
if (j + 1 < 100) {
solver.AddLead(GetIndex(i, j), 0, GetIndex(i, j + 1), 0);
}
}
solver.SetFalse(GetIndex(i, 0), 0);
solver.SetFalse(GetIndex(i, 100), 1);
}
for (int i = 0; i < m; ++i) {
if (rl[i] == "=") {
Add(id1[i], id2[i], op[i][0], ">=", val[i]);
Add(id1[i], id2[i], op[i][0], "<=", val[i]);
} else {
Add(id1[i], id2[i], op[i][0], rl[i], val[i]);
}
}
if (!solver.ExistSolution()) {
return {};
}
std::vector<int> result(n);
auto sol = solver.GetOneSolution();
for (int i = 0; i < n; ++i) {
for (int j = 1; j < 101; ++j) {
int t = GetIndex(i + 1, j);
if (!sol[t]) {
result[i] = j;
break;
}
}
}
return result;
} private:
void Add(int x, int y, char op, const std::string &rl, int z) {
if (op == '+' || op == '*') {
if (rl[0] == '<') {
AddMulLess(x, y, op, rl, z);
} else {
AddMulGreater(x, y, op, rl, z);
}
} else {
if (rl[0] == '<') {
SubDivLess(x, y, op, rl, z);
} else {
SubDivGreater(x, y, op, rl, z);
}
}
} void AddMulLess(int g1, int g2, char op, const std::string &rl, int z) {
// Assume g2 > i - 1, (i, i+1, i+2, ..., 100)
for (int i = 1; i <= 101; ++i) {
// If rl is '<', then 1000(i + j) < z.
// Here consider opposite: 1000(i + j) >= z.
// Get j >= ceil((z - 1000i) / 1000) = (z - 1000i + 999) / 1000
// So g2 >= i and g1 >= j conflicts
// If rl is '<=', then 1000(i + j) <= z.
// Here consider opposite: 1000(i + j) > z.
// Get j >= floor((z - 1000i) / 1000) + 1 = (z - 1000i + 1000) / 1000
// So g2 >= i and g1 >= j conflicts
int j = op == '+' ? Ceil(z - 1000 * i, 1000, EqualTag(rl))
: Ceil(z, i * 1000, EqualTag(rl));
if (j < 1) {
solver.SetFalse(GetIndex(g2, i - 1), 1);
} else if (j <= 101) {
solver.AddConflict(GetIndex(g2, i - 1), 1, GetIndex(g1, j - 1), 1);
}
}
} void AddMulGreater(int g1, int g2, char op, const std::string &rl, int z) {
for (int i = 0; i < 101; ++i) {
int j = op == '+' ? Floor(z - 1000 * i, 1000, EqualTag(rl))
: Floor(z, i * 1000, EqualTag(rl));
if (j >= 101) {
solver.SetFalse(GetIndex(g2, i), 0);
} else if (j >= 0) {
solver.AddConflict(GetIndex(g2, i), 0, GetIndex(g1, j), 0);
}
}
} void SubDivGreater(int g1, int g2, char op, const std::string &rl, int z) {
for (int i = 1; i <= 101; ++i) {
int j = op == '-' ? Floor(z + 1000 * i, 1000, EqualTag(rl))
: Floor(z * i, 1000, EqualTag(rl));
if (j >= 101) {
solver.SetFalse(GetIndex(g2, i - 1), 1);
} else if (j >= 0) {
solver.AddConflict(GetIndex(g2, i - 1), 1, GetIndex(g1, j), 0);
}
}
} void SubDivLess(int g1, int g2, char op, const std::string &rl, int z) {
for (int i = 0; i < 101; ++i) {
int j = op == '-' ? Ceil(z + 1000 * i, 1000, EqualTag(rl))
: Ceil(z * i, 1000, EqualTag(rl));
if (j < 1) {
solver.SetFalse(GetIndex(g2, i), 0);
} else if (j <= 101) {
solver.AddConflict(GetIndex(g2, i), 0, GetIndex(g1, j - 1), 1);
}
}
} bool EqualTag(const std::string &rl) { return rl.length() < 2; } int Ceil(int x, int y, bool tag) {
if (x < 0) {
return -1;
}
return (x + y - (tag ? 1 : 0)) / y;
} int Floor(int x, int y, bool tag) {
if (y == 0) {
return 101;
}
if (x <= 0) {
return -1;
}
return (x - (tag ? 0 : 1)) / y;
} int GetIndex(int i, int j) { return (i - 1) * 101 + j; } TwoSatisfiabilitySolver solver;
};
topcoder srm 630 div1 (2-SAT and SCC template)的更多相关文章
- Topcoder SRM 643 Div1 250<peter_pan>
Topcoder SRM 643 Div1 250 Problem 给一个整数N,再给一个vector<long long>v; N可以表示成若干个素数的乘积,N=p0*p1*p2*... ...
- Topcoder Srm 726 Div1 Hard
Topcoder Srm 726 Div1 Hard 解题思路: 问题可以看做一个二分图,左边一个点向右边一段区间连边,匹配了左边一个点就能获得对应的权值,最大化所得到的权值的和. 然后可以证明一个结 ...
- topcoder srm 714 div1
problem1 link 倒着想.每次添加一个右括号再添加一个左括号,直到还原.那么每次的右括号的选择范围为当前左括号后面的右括号减去后面已经使用的右括号. problem2 link 令$h(x) ...
- topcoder srm 738 div1 FindThePerfectTriangle(枚举)
Problem Statement You are given the ints perimeter and area. Your task is to find a triangle wi ...
- Topcoder SRM 608 div1 题解
Easy(300pts): 题目大意:有n个盒子,一共有S个苹果,每个盒子有多少个苹果不知道,但是知道每个盒子的苹果下限和上限.现在要至少选择X个苹果,问如果要保证无论如何都能获得至少X个苹果,至少需 ...
- Topcoder SRM 602 div1题解
打卡- Easy(250pts): 题目大意:rating2200及以上和2200以下的颜色是不一样的(我就是属于那个颜色比较菜的),有个人初始rating为X,然后每一场比赛他的rating如果增加 ...
- Topcoder SRM 627 div1 HappyLettersDiv1 : 字符串
Problem Statement The Happy Letter game is played as follows: At the beginning, several players ...
- Topcoder SRM 584 DIV1 600
思路太繁琐了 ,实在不想解释了 代码: #include<iostream> #include<cstdio> #include<string> #include& ...
- Topcoder SRM 630 (500 floyed 暴力 _builtin_popcount())
题意:给n个点,保证图联通,给点相连的距离,求一个最多的点,这些点之间的距离都是相同的. 分析: 下面的代码是我们房间第一的大神的,写的很简洁,我的思路和他的一样,但是我不知道错哪了. 思路是暴力枚举 ...
随机推荐
- 用jieba库统计文本词频及云词图的生成
一.安装jieba库 :\>pip install jieba #或者 pip3 install jieba 二.jieba库解析 jieba库主要提供提供分词功能,可以辅助自定义分词词典. j ...
- session and cookie
cookie cookie是由W3C组织提出,最早由Netscape社区发展的一种机制.目前Cookie已经成为标准,所有的主流浏览器如IE.Netscape.Firefox.Opera等都支持Coo ...
- vue 封装组件
props 接收数据 props对象里面 键值 是对改数据的 数据类型 的规定.做了规范,使用者就只能传输指定类型的数据,否则报警告 先根据要求写出完整的代码,再一一用参数实现组件封装 这里试着封装一 ...
- (转)测试如何区别是前端的问题还是后台的bug
常常说到的一个IT项目,包括前端开发,后台开发,软件测试,架构,项目经理,产品需求.那么对于一位优秀的软件测试工程师来说,需要区分前端和后台的工作就显得尤为重要. - 什么是前端和后台 简而言之,前端 ...
- visual studio 中被遗忘的任务列表和书签
任务列表(Task List)是VS中被人遗忘的一个功能,用到跳转到不同的代码段非常不便.以后就不用每次前进和后退导航了. 使用“任务列表” 跟踪使用 TODO 和 HACK或自定义令牌等令牌的代码注 ...
- vue+element-ui实现表格checkbox单选
公司平台利用vue+elementui搭建前端页面,因为本人第一次使用vue也遇到了不少坑,因为我要实现的效果如下图所示 实现这种单选框,只能选择一个,但element-ui展示的是多选框,check ...
- 关于iframe的一些操作
用于自己学习,本身对于js的一些东西没有深入了解,也是用到再去查 1.如果现在在一个页面,想要获取这个页面中的iframe中嵌入的页面中的一个指定id的div var iframeObj = docu ...
- NuGet的简单使用
什么是NuGet? NuGet(读作New Get)是用于微软.NET开发平台的软件包管理器,是一个Visual Studio的扩展.在使用Visual Studio开发基于.NET Framewor ...
- python 练习1(流控制)
#!/usr/bin/python #_*_ coding:utf-8 _*_ #练习题 #1.使用while循环输入 1 2 3 4 5 6 8 9 10 #a.定义一个变量存放数字 #b.用whi ...
- 【错误总结1:unity StartCoroutine 报 NullReferenceException 错误】
今天在一个项目中,写了一个单例的全局类,该类的作用是使用协程加载场景.但在StartCoroutine 这一步报了NullReferenceException 的错.仔细分析和搜索之后,得到错误原因. ...