首页 > 代码库 > 788B(dfs+xjb)

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 }
View Code

 

788B(dfs+xjb)