結果

問題 No.1254 補強への架け橋
ユーザー shirokami
提出日時 2023-08-19 10:28:58
言語 C++23
(gcc 13.3.0 + boost 1.87.0)
結果
AC  
実行時間 127 ms / 2,000 ms
コード長 9,722 bytes
コンパイル時間 5,991 ms
コンパイル使用メモリ 344,856 KB
実行使用メモリ 38,692 KB
最終ジャッジ日時 2024-11-29 02:03:08
合計ジャッジ時間 16,987 ms
ジャッジサーバーID
(参考情報)
judge4 / judge5
このコードへのチャレンジ
(要ログイン)
ファイルパターン 結果
sample AC * 3
other AC * 123
権限があれば一括ダウンロードができます

ソースコード

diff #
プレゼンテーションモードにする

#include <bits/extc++.h>
using namespace std;
// #pragma GCC optimize("O3")
// #pragma GCC optimize("unroll-loops")
// using namespace __gnu_pbds;
// #include <boost/multiprecision/cpp_int.hpp>
// using Bint = boost::multiprecision::cpp_int;
// #include <atcoder/all>
// using namespace atcoder;
// https://atcoder.github.io/ac-library/production/document_ja/
using uint = unsigned int;
using ll = long long;
using ull = unsigned long long;
using ld = long double;
constexpr ll mod = 1e9+7;
constexpr ll INF = 9'223'372'036'854'775'807/10;
#define rep(i,n) for (uint i = 0; i < uint(n); ++i)
#define All(a) (a).begin(),(a).end()
#define PI acos(-1)
vector<ll> dx = {1, 0, -1, 0, 1, 1, -1, -1};
vector<ll> dy = {0, 1, 0, -1, 1, -1, 1, -1};
template<class T>bool chmax(T &a, const T &b) { if (a<b) { a=b; return 1; } return 0; }
template<class T>bool chmin(T &a, const T &b) { if (b<a) { a=b; return 1; } return 0; }
struct Edge {
uint from, to;
long long cost;
int idx;
Edge() {}
Edge(uint from_, uint to_, long long cost_ = 1, int idx_ = -1) : from(from_), to(to_), cost(cost_), idx(idx_) {}
bool operator<(const Edge &e) const { return cost < e.cost; }
bool operator>(const Edge &e) const { return cost > e.cost; }
friend ostream& operator<<(ostream& os, const Edge& e) {
os << e.from << " " << e.to << " (" << e.cost << ")";
return os;
}
operator int() const { return to; }
};
struct Graph {
vector<vector<Edge>> G;
vector<Edge> edges;
Graph() {}
Graph(uint n) : G(n) {}
void add_edge(uint from, uint to, ll cost = 1, int idx = -1) {
G[from].emplace_back(from, to, cost, idx);
edges.emplace_back(from, to, cost, idx);
}
size_t size() const { return G.size(); }
vector<Edge>& operator[](int k) { return G[k]; }
friend ostream& operator<<(ostream& os, Graph& g) {
for (uint i = 0; i < g.size(); i++) {
for (Edge e : g[i]) {
cout << e << '\n';
}
}
return os;
}
};
struct IoSetup {
IoSetup() {
cin.tie(nullptr);
ios_base::sync_with_stdio(false);
cout << setprecision(15) << fixed;
}
} iosetup;
void print(const vector<string> &v) {
for (string s : v) {
cout << s << '\n';
}
}
template<typename T>
void print(const vector<pair<T, T>> &v, uint w = 0) {
for (uint i = 0; i < (uint)v.size(); i++) {
cout << right << setw(w) << v[i].first << ' ' << v[i].second << '\n';
}
}
template<typename T>
void print(const vector<T> &v, uint w = 0) {
for (uint i = 0; i < (uint)v.size(); i++) {
cout << right << setw(w) << v[i] << " \n"[i == (int)v.size() - 1];
}
}
template<typename T>
void print(const vector<vector<T>> &v, uint w = 0) {
for (uint i = 0; i < (uint)v.size(); i++) {
print(v[i], w);
}
}
template<typename T>
void print(const T& arg) {
cout << arg << '\n';
}
template<typename T, typename... Args>
void print(const T& arg, const Args&... args) {
cout << arg << ' ';
print(args...);
}
template<typename T>
istream& operator>>(istream& is, vector<T>& vec) {
for (auto& x : vec) is >> x;
return is;
}
/*
(NamoriGraph)
使:
NamoriGraph ng(n);
ng.add_edge(from, to, cost, idx); (0-indexed). 1 add_edge 2 ()
ng.build();
ng.forest[i]: i (0-indexed). from, to (0-indexed), cost, idx
ng.loop_edges[i]: i (0-indexed) . from, to, cost, idx .
ng[k]: k , tree_id, id
ng.inv(tree_id, id): tree_id id . id = 0
:
O(n)
:
https://ei1333.github.io/library/graph/others/namori-graph.hpp
*/
struct NamoriGraph {
// g:
// forest:
// loop_edges:
// iv: , ->
// iv[i][j]: ij
// mark_id: ->
// id: ->
Graph g;
vector<Graph> forest;
vector<Edge> loop_edges;
vector<vector<int>> iv;
vector<int> mark_id, id;
NamoriGraph() {}
NamoriGraph(uint n) : g(n) {}
NamoriGraph(const Graph &g_) : g(g_) {}
void add_edge(uint from, uint to, long long cost = 1, int idx = -1) {
if (idx == -1) idx = (int)g.edges.size()/2; // idx = /2
g.add_edge(from, to, cost, idx);
g.add_edge(to, from, cost, idx);
}
struct Info {
// tree_id:
// id:
int tree_id, id;
};
// k , tree_id, id
Info operator[](const int &k) const {
return (Info){mark_id[k], id[k]};
}
// tree_id id
// id = 0
int inv(int tree_id, int id_) {
return iv[tree_id][id_];
}
void build() {
int n = g.size();
// deg:
// used: 使
vector<int> deg(n), used(n);
queue<int> que;
// 1 ()
for (int i = 0; i < n; i++) {
deg[i] = g[i].size();
if (deg[i] == 1) {
que.emplace(i);
used[i] = true;
}
}
while (!que.empty()) {
int idx = que.front();
que.pop();
for (Edge &e : g[idx]) {
if (used[e.to]) {
continue;
}
// 1 1
deg[e.to]--;
// 1 ()
if (deg[e.to] == 1) {
que.emplace(e.to);
used[e.to] = true;
}
}
}
vector<int> edge_used(g.edges.size()/2 + 1);
vector<int> loop;
// loop
for (int v = 0; v < n; v++) {
// loop 1
if (!used[v]) {
//
for (bool update = true; update; ) {
update = false;
loop.emplace_back(v);
// loop or 使
for (Edge &e : g[v]) {
if (used[e.to] || edge_used[e.idx]) { // edge_used !!!!!!!!!!!
continue;
}
edge_used[e.idx] = true; // e.idx 使
loop_edges.emplace_back(v, e.to, e.cost, e.idx); // 使
v = e.to; //
update = true;
break;
}
}
break;
}
}
//
loop.pop_back();
mark_id.resize(n);
id.resize(n);
for (int i = 0; i < (int)loop.size(); i++) {
int pre = loop[(i + (int)loop.size() - 1) % loop.size()]; //
int cur = loop[i]; //
int nxt = loop[(i + 1) % loop.size()]; //
int sz = 0; //
// mark_id: ->
mark_id[cur] = i;
// iv[i][j]: ij
iv.emplace_back();
iv.back().emplace_back(cur);
//
id[cur] = sz++;
for (Edge &e : g[cur]) {
if (e.to != pre && e.to != nxt) { //
mark_dfs(e.to, cur, i, sz); //
}
}
Graph tree(sz);
for (Edge &e : g[cur]) {
if (e.to != pre && e.to != nxt) { //
tree[id[cur]].emplace_back(id[cur], id[e.to], e.cost, e.idx); //
tree[id[e.to]].emplace_back(id[e.to], id[cur], e.cost, e.idx); //
build_dfs(e.to, cur, tree); //
}
}
forest.emplace_back(tree); //
}
}
// mark_dfs:
// idx:
// par:
// tree_id:
// sz:
void mark_dfs(int idx, int par, int tree_id, int &sz) {
mark_id[idx] = tree_id; // idx tree_id
iv[tree_id].emplace_back(idx); // tree_id sz idx
id[idx] = sz++; // idx sz
for (Edge &e : g[idx]) { // idx
if (e.to != par) { //
mark_dfs(e.to, idx, tree_id, sz); //
}
}
}
void build_dfs(int idx, int par, Graph &tree) {
for (Edge &e : g[idx]) { // idx
if (e.to != par) { //
tree[id[idx]].emplace_back(id[idx], id[e.to], e.cost, e.idx); //
tree[id[e.to]].emplace_back(id[e.to], id[idx], e.cost, e.idx); //
build_dfs(e.to, idx, tree); //
}
}
}
};
void solve() {
ll n;
cin >> n;
NamoriGraph ng(n);
rep(i,n) {
ll a, b;
cin >> a >> b;
a--; b--;
ng.add_edge(a, b);
}
ng.build();
cout << ng.loop_edges.size() << '\n';
for (auto e : ng.loop_edges) {
cout << e.idx+1 << ' ';
}
cout << '\n';
}
int main() {
uint t = 1;
// cin >> t;
while (t--) {
solve();
}
}
הההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההה
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
0