(权限题)NFLSoj #29: 环 题解

博客探讨了一种解决环形问题的策略,通过枚举中心点并分析与之相连的点集,再将剩余点按联通块划分。关键在于找到特定点集间不相邻的点,以此构建解。整体解决方案的时间复杂度为O(nm),适用于包含环的图论问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

我们枚举一个中心点,称为X

将与中心点相连的点取出来,这个点集称为S

剩下的点按照联通块分成若干个点集,设第i个联通块构成的点集为Ti

找出S中与Ti中任意一点相邻的所有点,这个点集称为Gi

如果Gi中存在两个不相邻的点,那么原图一定有解

这个解是:中心点,Gi中不相邻的两个点,以及与这两个点相邻的Ti中的两个点的最短路径上的所有点,最短路径上的点是不会有不满足题意的情况的

这样总复杂度O(nm)

#include <cstdio>
#include <iostream>
#include <cstring>
#include <string>
#include <cstdlib>
#include <utility>
#include <cctype>
#include <algorithm>
#include <bitset>
#include <set>
#include <map>
#include <vector>
#include <queue>
#include <deque>
#include <stack>
#include <cmath>
#define LL long long
#define LB long double
#define x first
#define y second
#define Pair pair<int,int>
#define pb push_back
#define pf push_front
#define mp make_pair
#define LOWBIT(x) x & (-x)
using namespace std;

const int MOD=1e9+7;
const LL LINF=2e16;
const int INF=2e9;
const int magic=348;
const double eps=1e-10;

inline int getint()
{
	char ch;int res;bool f;
	while (!isdigit(ch=getchar()) && ch!='-') {}
	if (ch=='-') f=false,res=0; else f=true,res=ch-'0';
	while (isdigit(ch=getchar())) res=res*10+ch-'0';
	return f?res:-res;
}

int n,e;
vector<int> v[1048];
bool ga[1048][1048];
bool S[1048];
bool visited[1048];
bool added[1048];
vector<int> G;
vector<int> G1;

void dfs(int cur)
{
	int i;
	visited[cur]=true;
	G.pb(cur);
	for (i=0;i<v[cur].size();i++)
		if (!visited[v[cur][i]])
		{
			if (S[v[cur][i]])
			{
				if (!added[v[cur][i]])
				{
					G1.pb(v[cur][i]);
					added[v[cur][i]]=true;
				}
				continue;
			}
			dfs(v[cur][i]);
		}
}

int main ()
{
	int i,j,k,cen,x,y;
	n=getint();e=getint();
	for (i=1;i<=e;i++)
	{
		x=getint();y=getint();
		v[x].pb(y);v[y].pb(x);
		ga[x][y]=true;ga[y][x]=true;
	}
	for (cen=1;cen<=n;cen++)
	{
		memset(S,false,sizeof(S));memset(visited,false,sizeof(visited));
		for (i=0;i<v[cen].size();i++) S[v[cen][i]]=true;
		for (i=1;i<=n;i++)
			if (i!=cen && !visited[i] && !S[i])
			{
				memset(added,false,sizeof(added));
				G.clear();G1.clear();
				dfs(i);
				int num=G1.size();
				for (j=0;j<G1.size();j++)
					for (k=0;k<G1.size();k++)
						if (G1[j]!=G1[k] && !ga[G1[j]][G1[k]])
						{
							printf("yes\n");
							return 0;
						}
			}
	}
	printf("no\n");
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值