n个点, m条边, 问最少加几条边可以出现一个奇环, 在这种情况下, 有多少种加边的方式。
具体看代码解释
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define pb(x) push_back(x) 4 #define ll long long 5 #define mk(x, y) make_pair(x, y) 6 #define lson l, m, rt<<1 7 #define mem(a) memset(a, 0, sizeof(a)) 8 #define rson m+1, r, rt<<1|1 9 #define mem1(a) memset(a, -1, sizeof(a)) 10 #define mem2(a) memset(a, 0x3f, sizeof(a)) 11 #define rep(i, a, n) for(int i = a; i<n; i++) 12 #define ull unsigned long long 13 typedef pair<int, int> pll; 14 const double PI = acos(-1.0); 15 const double eps = 1e-8; 16 const int mod = 1e9+7; 17 const int inf = 1061109567; 18 const int dir[][2] = { {-1, 0}, {1, 0}, {0, -1}, {0, 1} }; 19 const int maxn = 1e5+5; 20 int de[maxn], white[maxn], black[maxn], color[maxn], head[maxn*2], num, flag; 21 struct node 22 { 23 int to, nextt; 24 }e[maxn*2]; 25 void add(int u, int v) { 26 e[num].to = v; 27 e[num].nextt = head[u]; 28 head[u] = num++; 29 } 30 void dfs(int u, int c, int s) { //每一个cnt代表一个联通块, c是颜色 31 color[u] = c; 32 if(c&1) 33 black[s]++; 34 else 35 white[s]++; 36 for(int i = head[u]; ~i; i = e[i].nextt) { 37 int v = e[i].to; 38 if(!color[v]) { 39 dfs(v, 3-c, s); 40 } else if(color[v]==color[u]) { //这是本身就有奇环 41 flag = 1; 42 } 43 } 44 } 45 int main() 46 { 47 int n, m; 48 cin>>n>>m; 49 if(!m) { 50 cout<<3<<" "<<1ll*n*(n-1)*(n-2)/6; //一条边也没有 51 return 0; 52 } 53 int x, y; 54 mem1(head); 55 for(int i = 1; i<=m; i++) { 56 scanf("%d%d", &x, &y); 57 de[x]++, de[y]++; 58 add(x, y); 59 add(y, x); 60 if(de[x]>1||de[y]>1) { 61 flag = 1; 62 } 63 } 64 if(!flag) { 65 cout<<2<<" "<<1ll*m*(n-2)<<endl; //这种情况是有边, 但是所有的边都不相连 66 return 0; 67 } 68 flag = 0; 69 int cnt = 0; 70 for(int i = 1; i<=n; i++) { 71 if(!color[i]) { 72 dfs(i, 1, ++cnt); 73 } 74 if(flag) { 75 puts("0 1"); 76 return 0; //本身就有奇环 77 } 78 } 79 ll ans = 0; 80 for(int i = 1; i<=cnt; i++) { 81 ans += 1ll*(white[i]-1)*white[i]+1ll*black[i]*(black[i]-1); //每一个联通块里面的种数累加。 82 } 83 cout<<1<<" "<<ans/2<<endl; 84 return 0; 85 }