D - Weird journey
题意:
n个城市,m条路,现在要找出这样的路:经过m-2条路两次,其它两条路经过一次。
问:有多少这样的路径。
思路:
- 一定要看清楚题。
根据题意发现类似于欧拉图,根据欧拉图的定义只有满足两个条件的才能画出图, 不妨把经过两次的边转化为欧拉图,根据欧拉图“一笔画”性质,可以得出肯定是相邻边,并且无论相邻节点的度是多少都能连城欧拉路,所以目的就是找出多少相邻边。
还有一种情况是自环,对于自环其实就是自己在自己节点上走了两次,所以可以和任何一条边结合,当然不能连接两个自环的边,所以减去即可。
#include <iostream>
#include <cstring>
#include <vector>
#include <cstdio>
using namespace std;
const int maxn = 1e6+10;
int n,m,vis[maxn];
vector<int>mp[maxn];
int numb[maxn];
void dfs(int u)
{
vis[u] = true;
int Size = mp[u].size();
for(int i = 0;i < Size; i++) {
if(!vis[mp[u][i]]) {
dfs(mp[u][i]);
}
}
}
int main()
{
//freopen("in.txt","r",stdin);
scanf("%d%d",&n,&m);
long long STR = 0;
for(int i = 1;i <= m; i++) {
int u,v;
scanf("%d%d",&u,&v);
numb[u]++,numb[v]++;
if(u != v) {
mp[u].push_back(v);
mp[v].push_back(u);
}
else STR++;
}
for(int i = 1;i <= n; i++) {
if(mp[i].size()) {
dfs(i);
break;
}
}
for(int i = 1;i <= n; i++) {
if(!vis[i] && numb[i]) {
printf("0\n");
return 0;
}
}
long long ans = 0;
for(int i = 1;i <= n; i++) {
ans += 1ll*mp[i].size()*(mp[i].size()-1)/2;
}
ans += STR*(m-1) - STR*(STR-1)/2;
printf("%I64d\n",ans);
return 0;
}