788B(dfs+xjb)
题目链接: http://codeforces.com/problemset/problem/788/B
题意: 给出一个有 n 个顶点和 m 条边的图(没有重边,可能有自环), 可以从中任意一个顶点开始(一笔画), 要求经过其中 m - 2 条边 2 次, 2 条边一次, 求共有多少种满足要求的方案.
思路: 首先要是给出的图是非边联通的话, 答案肯定为 0.
对于边联通的图, 我们可以枚举两条经过一次的边中的一条, 再分析另一条边.
对于第 i 条边, 若其为非自环边, 那么可以与其组合的边为此边的邻边(左邻边, 右邻边) 以及自环的边.
若其为自环边, 则可以和剩下边任意一条组合.
将上面的情况求和再除二即为答案.
代码:
1 #include <iostream> 2 #include <stdio.h> 3 #include <vector> 4 #define ll long long 5 using namespace std; 6 7 const int MAXN = 1e6 + 10; 8 vector<int> vt[MAXN]; 9 int x[MAXN], y[MAXN], in[MAXN], vis[MAXN]; 10 11 void dfs(int v){ 12 vis[v] = 1; 13 for(int i = 0; i < vt[v].size(); i++){ 14 if(!vis[vt[v][i]]) dfs(vt[v][i]); 15 } 16 } 17 18 int main(void){ 19 ll sol = 0; 20 int n, m, gel = 0; 21 scanf("%d%d", &n, &m); 22 for(int i = 0; i < m; i++){ 23 scanf("%d%d", &x[i], &y[i]); 24 if(x[i] != y[i]){ 25 vt[x[i]].push_back(y[i]); 26 vt[y[i]].push_back(x[i]); 27 }else gel++; 28 in[x[i]]++; 29 in[y[i]]++; 30 } 31 dfs(x[0]);//判断是否为边联通图 32 for(int i = 1; i <= n; i++){ 33 if(!vis[i] && in[i]){ 34 puts("0"); 35 return 0; 36 } 37 } 38 for(int i = 0; i < m; i++){ 39 if(x[i] != y[i]) sol += (ll)(vt[x[i]].size() - 1 + vt[y[i]].size() - 1 + gel); 40 else sol += (ll)(m - 1); 41 } 42 printf("%lld\n", sol/2ll); 43 return 0; 44 }
我就是我,颜色不一样的烟火 --- geloutingyu