我是靠谱客的博主 负责白云,最近开发中收集的这篇文章主要介绍[CSP-S模拟测试]:星际旅行(欧拉路),觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

题目传送门(内部题4)


输入格式

第一行两个整数$n,m$,表示行星和虫洞的数量。
接下来$m$行,每行两个整数$u,v$,表示存在一个双向虫洞直接连接$u$和$v$。
每一个虫洞最多会被描述一次。


输出格式

一行一个整数,代表本质不用的航线的数量。


样例

样例输入

5 4
1 2
1 3
1 4
1 5

样例输出

6


数据范围与提示

样例解释:
本质不同的航线有$6$条:
2-1-3-1-4-1-5
2-1-3-4-5-1-4
2-1-4-1-5-1-3
3-1-2-1-5-1-4
3-1-2-1-4-1-5
4-1-2-1-3-1-5
注意2-1-4-1-3-1-5不是另一个本质不同的航线,它与第一条航线是本质相同的。

限制与约定:
对于$10%$的数据,$n,m leqslant 5$。
对于$20%$的数据,$n,m leqslant 10$。
对于$40%$的数据,$n,m leqslant 100$。
对于$60%$的数据,$n,m leqslant 1000$。
对于所有的数据,$1 leqslant n,m leqslant {10}^5,1 leqslant u,v leqslant n$。


题解

将所有的边拆成两条,问题变成删掉两条边,使得剩下的图是一个欧拉路或者是欧拉回路。

则分为三种情况:

  1.删掉两个自环:删掉两个自环,这两个点的度数都$-2$,成为一个欧拉回路,假设这样的点有$sum$个,则方案数为$C_{sum}^2$。

  2.删掉一个自环和一条边:删自环上面已经说明了,考虑删边,删去一条边则这两个点的度数$-1$,变为两个奇数点,成为一个欧拉路,方案数为$C_{sum}^2 times (m-sum)$。

  3.删掉有一个公共点的两条边:该点的度数$-2$,两条边分别连接的另两个点的度数分别$-1$,成为一个欧拉路,方案数为$sum limits_{i=1}^n C_{d[i]}^2$。

则总的方案数为:$C_{sum}^2 + C_{sum}^2 times (m-sum) + sum limits_{i=1}^n C_{d[i]}^2$。

至于计算过程,显然上面的方法不方便计算,那么我们考虑转化一下计算的思路。

将情况$1$和情况$2$和起来,则第一个自环可以与剩余边结合,方案数为$m-1$,第二个自环贡献的方案数为$m-2$,根据高中课本中等差数列求和公式可得方案数为:$frac{(2 times m-sum-1) times sum}{2}$。

情况3的方案数为:$frac{sum limits_{i=1}^n d[i] times (d[i]-1)}{2}$,扫一边即可求出。

注意图不连通的判断方式,不是点不连通,而是边不连通,可以使用并差集判断,不联通方案数为$0$。


代码时刻

#include<bits/stdc++.h>
using namespace std;
int n,m;
int rd_geq[100001],rd_leq[100001],f[100001];
long long ans,sum;
int find(int x){return f[x]==x?x:f[x]=find(f[x]);}
void connect(int x,int y){f[find(x)]=find(y);}
int main()
{
	int n,m;
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++)f[i]=i;
	for(int i=1;i<=m;i++)
	{
		int x,y;
		scanf("%d%d",&x,&y);
		rd_leq[x]++;//所有的度
		rd_leq[y]++;
		if(x==y)sum++;//统计自环
		else
		{
			rd_geq[x]++;//非自环的度
			rd_geq[y]++;
			connect(x,y);
		}
	}
	int flag=0;
	for(int i=1;i<=n;i++)
		if(rd_leq[i])
		{
			flag=i;
			break;
		}
	for(int i=1;i<=n;i++)
	{
		if(rd_leq[i]&&find(i)!=f[flag])
		{
			puts("0");
			return 0;
		}
		ans+=1LL*(rd_geq[i]-1)*rd_geq[i]/2;//第3种情况
	}
	ans+=sum*(m-sum)+sum*(sum-1)/2;//第1种和第2种情况
	printf("%lld",ans);
	return 0;
}

rp++

转载于:https://www.cnblogs.com/wzc521/p/11222447.html

最后

以上就是负责白云为你收集整理的[CSP-S模拟测试]:星际旅行(欧拉路)的全部内容,希望文章能够帮你解决[CSP-S模拟测试]:星际旅行(欧拉路)所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(56)

评论列表共有 0 条评论

立即
投稿
返回
顶部