atcoder/CODE FESTIVAL 2017 qual B/B(dfs染色判断是否为二分图)
题目链接:http://code-festival-2017-qualb.contest.atcoder.jp/tasks/code_festival_2017_qualb_c
题意:给出一个含 n 个顶点 m 条边的图,对于图中两点 u, v 之间可以添加一条边当且仅当 u, v 是通过三条边连接在一起时,求最多可以添加多少条边.
思路:猜结论,当给出的图是二分图时,sol = st1.size() * st2.size() - m,其中 st1.size(), st2.size() 二分图两边的顶点数.
当给出的图不是二分图时,sol = n * (n - 1) / 2 - m.
代码:
1 #include <bits/stdc++.h> 2 #define ll long long 3 using namespace std; 4 5 const int MAXN=1e5+10; 6 vector<int> v[MAXN]; 7 vector<int> st1, st2; 8 bool flag=false; 9 int vis[MAXN]; 10 11 void dfs(int point){ 12 if(flag){ 13 return; 14 } 15 for(int i=0; i<v[point].size(); i++){ 16 int cnt=v[point][i]; 17 if(vis[point]==vis[cnt]){ 18 flag=true; 19 return; 20 }else if(!vis[cnt]){ 21 if(vis[point]==1){ 22 vis[cnt]=2; 23 st2.push_back(cnt); 24 dfs(cnt); 25 }else if(vis[point]==2){ 26 vis[cnt]=1; 27 st1.push_back(cnt); 28 dfs(cnt); 29 } 30 } 31 } 32 } 33 34 int main(void){ 35 ios::sync_with_stdio(false), cin.tie(0), cout.tie(0); 36 int n, m, x, y; 37 cin >> n >> m; 38 for(int i = 0; i < m; i++){ 39 cin >> x >> y; 40 v[x].push_back(y); 41 v[y].push_back(x); 42 } 43 for(int i=1; i<=n; i++){ 44 if(v[i].size()==0){ 45 continue; 46 }else if(!vis[i]){ 47 vis[i]=1; 48 st1.push_back(i); 49 dfs(i); 50 } 51 } 52 ll cnt; 53 if(flag) cnt = (ll)n * (n - 1) / 2 - m; 54 else cnt = (ll)st1.size() * st2.size() - m; 55 cout << cnt << endl; 56 return 0; 57 }
我就是我,颜色不一样的烟火 --- geloutingyu