CODE FESTIVAL 2017 qual B C問題 3 Steps
問題
code-festival-2017-qualb.contest.atcoder.jp
解説
辺を3本巡って到達できる頂点と辺を新たに結ぶので、2頂点間に奇数長のパスが存在すれば辺を結ぶことができます。 では奇数長のパスが存在するとはどのような時なのでしょうか。それは2分グラフであるかどうかに影響されます。 * 2分グラフである場合 辺を結ぶことができるのは色が異なる頂点間です。それは同色であると必ずパスの長さが偶数になるからです。 よって黒と白に塗り分けるとすると、黒の頂点数=b, 白の頂点数=wとすると bC1 * wC1 が結ぶことができる辺の数であり、すでに結ばれている辺の数Mを引いた値が答えになります。 * 2分グラフでない場合 必ず奇数長のサイクルが存在するので全ての2頂点間のパスの中に奇数長のパスが存在することになり、任意の2頂点間を辺で結ぶことができるためnC2-mが答えになります。
コード
#include <iostream> #include <string> #include <algorithm> #include <set> #include <map> #include <vector> #include <queue> using namespace std; const long long inf = 1e10; const long long mod = 1e9+7; typedef vector<vector<int> > G; G graph; int color[100050]; bool dfs(int u, int c){ color[u] = c; for(int i=0; i<graph[u].size(); i++){ int v = graph[u][i]; if(color[v] == c){ return false; } if(color[v] == 0 && !dfs(v, -c) ){ return false; } } return true; } int main(void){ long long n, m; cin >> n >> m; graph = G(n); for(int i=0; i<m; i++){ int x, y; cin >> x >> y; x--; y--; graph[x].push_back(y); graph[y].push_back(x); } long long B=0, W=0; if(dfs(0, 1)){ for(int i=0; i<n; i++){ if(color[i] == 1){ B++; }else if(color[i] == -1){ W++; } } cout << B*W - m << endl; }else{ cout << ( (n*(n-1)) /2) - m << endl; } return 0; }