专栏文章

题解:CF1276B Two Fairs

CF1276B题解参与者 1已保存评论 0

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
0 条
当前快照
1 份
快照标识符
@min10sju
此快照首次捕获于
2025/12/01 18:48
3 个月前
此快照最后确认于
2025/12/01 18:48
3 个月前
查看原文

题目大意

有一个无向图,其中 nn 个点。给出两个关键节点 aabb,求有多少对点 xxyyxax \ne axbx \ne byay \ne ayby \ne b),使得在所有从 xxyy 的路径都经过 aabb

思路

要使得路径经过 aabb 则此节点必须经过 aabb,这相当于在移除 aabb 后,剩下的图被分成了两个独立的连通块(一个包含 aa,另一个包含 bb)。所以,在第一个连通块中的点 xx,和在第二个连通块中的点 yy,它们之间的路径都必须经过 aabb。根据乘法原理,路径对数就是两个连通块大小的乘积。
代码CPP
#include<bits/stdc++.h>
using namespace std;
long long n,m,a,b,vis[1000004],lt,rt,T;
map<long long,long long>l,r;
vector<long long>edge[1000005];
void findA(long long x)
{
	long long u=x;
	for(long long i=0;i<edge[u].size();i++)
	{
		if(!vis[edge[u][i]])
		{
			vis[edge[u][i]]=1;
			if(edge[u][i]!=b)
			{
				l[edge[u][i]]=1;
				findA(edge[u][i]);
			}
		}
	}
}
void findB(long long x)
{
	long long u=x;
	for(long long i=0;i<edge[u].size();i++)
	{
		if(!vis[edge[u][i]])
		{
			vis[edge[u][i]]=1;
			if(edge[u][i]!=a)
			{
				if(l[edge[u][i]]==1)
					l[edge[u][i]]=0;
				else r[edge[u][i]]=1;
				findB(edge[u][i]);
			}
		}
	}
}
signed main()
{
	scanf("%lld",&T);
	while(T--)
	{
		scanf("%lld%lld%lld%lld",&n,&m,&a,&b);
		l.clear();
		r.clear();
		memset(vis,0,sizeof(vis));
		for(int i=0;i<=n;i++)//初始化
			edge[i].clear();
		for(long long i=1;i<=m;i++)
		{
			long long u,v;
			scanf("%lld%lld",&u,&v);
			edge[u].push_back(v);
			edge[v].push_back(u);
		}
		vis[a]=1;
		findA(a);// 第一次找到与a连通但不包含b的连通块
		memset(vis,0,sizeof(vis));
		vis[b]=1;
		findB(b);// 第二次找到与b连通但不包含a的连通块
		lt=0,rt=0;
		map<long long,long long>::iterator it;
		for(it=l.begin();it!=l.end();it++)
			if(it->second!=0)lt++;
		for(it=r.begin();it!=r.end();it++)
			if(it->second!=0)rt++;
		printf("%lld\n",lt*rt);// 计算满足条件的城市对数
	}
	return 0;
}

评论

0 条评论,欢迎与作者交流。

正在加载评论...