Codeforces Round #407 D. Weird journey(欧拉路径+并查集 / 搜索)

本文探讨了在一个无向图中寻找特定路径的问题,重点在于如何确保每条边被访问的次数符合要求,并讨论了欧拉路径的存在条件及计算方法。

题意

给定 n 个城市 m 条无向路(无向路存在自环的情况),问能够找到多少条不同的路径,使得其中 m-2 条路径被走过 2 次,剩下 2 条路径被走过 1 次。

两条路径被视为不同的,当且仅当走过走过 1 次的两条路不同。

分析

该题不考虑一定要经过所有点,仅需考虑都过 m-2 条路 2 次,剩下 2 条路 1 次即可。

无向图存在欧拉路当且仅当它是连通的,且除了恰好两个顶点外,其余所有顶点的度为偶数。

考虑 m 条路都需要经过两次的情况,可视作是原图中直接相连的两点当前存在两条相同的边,故图中所有点的度数必为偶数,则欧拉路径一定存在。此时,要求从上述 2*m 条边中删去两端点不同的两边。

  • 若该两边没有公共端点,必然导致此时 2*m 条边的图中有 4 个点(该两边的端点)的度为奇数,即不存在欧拉路

故要删去的两边必然存在公共端点,即计算每个点的度为 cnti ,则每个连通图中的点对答案的贡献为 C2cnti

上述考虑的是没有自环的情况,当存在自环时:

  • 删除两个自环边,由于自环边两端连接同一点,故不会对连通图中点的度奇偶性产生影响。对答案的贡献为 C2loop ,记自环边的条数为 loop
  • 删除一个自环边和一条非自环边,此时连通图中产生 2 个点的度为奇数,仍存在欧拉路径。该情况有 loop×(mloop) 种。

至于判断图的连通性,可以考虑使用 并查集 或者 搜索 等方案都可;对于不连通的图,显然,必然不存在欧拉路径。

代码

#include<bits/stdc++.h>
using namespace std;
const int V = 1e6 + 10;
int n, m, fa[V];
long long loop, cnt, deg[V];
int find(int x) {   return fa[x] = fa[x] == x ? x : find(fa[x]);    }
void Union(int u, int v) {
    int fx = find(u),   fy = find(v);
    fa[fx] = fy;
}
set<int> st;
int main()
{
    scanf("%d %d",&n,&m);
    for(int i=1;i<=n;i++)
        fa[i] = i;
    for(int i=0, u, v;i<m;i++)
    {
        scanf("%d %d",&u,&v);
        if(u == v)  loop++;
        else    deg[u]++,   deg[v]++;
        st.insert(u), st.insert(v);
        Union(u, v);
    }
    long long ans = 0;
    for(set<int>::iterator it=st.begin();it!=st.end();it++)
    {
        if(find(*it) != find(*st.begin())) {
            printf("0\n");
            return 0;
        }
        ans += deg[*it] * (deg[*it]-1) / 2;
    }
    ans += loop * (loop-1) / 2;
    ans += loop * (m-loop);
    printf("%I64d\n", ans);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值