-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #97 from rainbou-kpr/graph_util
add graph_util
- Loading branch information
Showing
4 changed files
with
151 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,119 @@ | ||
#pragma once | ||
|
||
/** | ||
* @file graph_util.hpp | ||
* @brief グラフに関する関数 | ||
*/ | ||
|
||
#include <stack> | ||
|
||
#include "graph.hpp" | ||
|
||
/** | ||
* @brief 無向グラフについて、二部グラフなら0と1に彩色した結果をひとつ返し、二部グラフでないなら空のvectorを返す。 | ||
* 連結成分のうち、インデックスの最も小さいものを0にする。 | ||
* @return std::vector<int> 各頂点の彩色結果 | ||
*/ | ||
template <typename Cost = int> | ||
std::vector<int> bipartite_coloring(const Graph<Cost>& graph) { | ||
std::vector<int> color(graph.n, -1); | ||
for (int i = 0; i < graph.n; i++) { | ||
if (color[i] != -1) continue; | ||
std::stack<int> stk; | ||
stk.push(i); | ||
color[i] = 0; | ||
while (!stk.empty()) { | ||
int u = stk.top(); | ||
stk.pop(); | ||
for (int v : graph[u]) { | ||
if (color[v] == -1) { | ||
color[v] = color[u] ^ 1; | ||
stk.push(v); | ||
} else { | ||
if (color[u] == color[v]) return {}; | ||
} | ||
} | ||
} | ||
} | ||
return color; | ||
} | ||
|
||
/** | ||
* @brief 無向グラフについて、二部グラフかどうかを判定する。 | ||
* @return bool 二部グラフならtrue、二部グラフでないならfalseを返す。 | ||
*/ | ||
template <typename Cost = int> | ||
bool is_bipartite(const Graph<Cost>& graph) { | ||
return !bipartite_coloring(graph).empty(); | ||
} | ||
|
||
/** | ||
* @brief 無向グラフについて、連結成分分解する。 | ||
* @return std::vector<std::vector<int>> 「同じ連結成分となる頂点のリスト」のリスト | ||
*/ | ||
template <typename Cost = int> | ||
std::vector<std::vector<int>> connected_components(const Graph<Cost>& graph) { | ||
std::vector<std::vector<int>> groups; | ||
std::vector<bool> visited(graph.n); | ||
for (int i = 0; i < graph.n; i++) { | ||
if (visited[i]) continue; | ||
std::stack<int> stk; | ||
stk.push(i); | ||
visited[i] = true; | ||
groups.push_back({i}); | ||
while (!stk.empty()) { | ||
int u = stk.top(); | ||
stk.pop(); | ||
for (int v : graph[u]) { | ||
if (visited[v]) continue; | ||
visited[v] = true; | ||
stk.push(v); | ||
groups.back().push_back(v); | ||
} | ||
} | ||
} | ||
return groups; | ||
} | ||
|
||
/** | ||
* @brief 無向グラフについて、連結グラフかどうかを判定する。 | ||
* @return bool 連結グラフならtrue、連結グラフでないならfalseを返す。 | ||
*/ | ||
template <typename Cost = int> | ||
bool is_connected(const Graph<Cost>& graph) { | ||
return connected_components(graph).size() == 1; | ||
} | ||
|
||
/** | ||
* @brief 無向グラフについて、木かどうかを判定する。 | ||
* @return bool 木ならtrue、木でないならfalseを返す。 | ||
*/ | ||
template <typename Cost = int> | ||
bool is_tree(const Graph<Cost>& graph) { | ||
return graph.m == graph.n - 1 && is_connected(graph); | ||
} | ||
|
||
/** | ||
* @brief 有向グラフをトポロジカルソートする | ||
* @param G トポロジカルソートするグラフ | ||
* @return ソートされたノード番号のvector DAGでなければ長さがG.n未満になる | ||
*/ | ||
template<typename Cost> | ||
std::vector<int> topological_sort(const Graph<Cost> &G) { | ||
std::vector<int> indeg(G.n), sorted; | ||
std::queue<int> q; | ||
for (int i = 0; i < G.n; i++) { | ||
for (int dst : G[i]) indeg[dst]++; | ||
} | ||
for (int i = 0; i < G.n; i++) { | ||
if (!indeg[i]) q.push(i); | ||
} | ||
while (!q.empty()) { | ||
int cur = q.front(); q.pop(); | ||
for (int dst : G[cur]) { | ||
if (!--indeg[dst]) q.push(dst); | ||
} | ||
sorted.push_back(cur); | ||
} | ||
return sorted; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
#define PROBLEM "https://atcoder.jp/contests/abc282/tasks/abc282_d" | ||
|
||
#include <algorithm> | ||
#include <array> | ||
|
||
#include "../cpp/graph_util.hpp" | ||
|
||
int main(void) { | ||
int N, M; | ||
std::cin >> N >> M; | ||
Graph<int> graph(N); | ||
graph.read(M); | ||
std::vector<int> c = bipartite_coloring(graph); | ||
if (c.empty()) { | ||
std::cout << 0 << std::endl; | ||
return 0; | ||
} | ||
std::vector<std::vector<int>> groups = connected_components(graph); | ||
long long ans = (long long)N * (N - 1) / 2 - M; | ||
for (const std::vector<int>& group : groups) { | ||
std::array<long long, 2> wb = {}; | ||
std::for_each(group.begin(), group.end(), [&](int x) { wb[c[x]]++; }); | ||
auto [w, b] = wb; | ||
ans -= w * (w - 1) / 2 + b * (b - 1) / 2; | ||
} | ||
std::cout << ans << std::endl; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters