为什么TLE一个点
查看原帖
为什么TLE一个点
930104
Naegi_Makoto楼主2023/10/26 16:38

思路是

先用并查集把有关联的点都连接起来,再每个点进行遍历,对于每个连通块的祖先节点进行标记,发现遍历了两次的点后从发现环的点开始跑,记录经过的边数,直到再次遇到该点。

每个连通块应该只会被访问一次,全图遍历复杂度为 O(2n)O(2n) 吧。为什么会T呢?

代码在这里了

#include<bits/stdc++.h>
#define ll long long
using namespace std;
inline ll read(){
	ll num = 0;
	ll x = 1;
	char ch = getchar();
	while( !isdigit(ch) ){
		if( ch == '-' )
			x = -1;
		ch = getchar();
	}
	while( isdigit(ch) ){
		num = num * 10 + ch - '0';
		ch = getchar();
	}
	return num * x;
}

bool vis[200005];
int nxt[200005];
int fa[200005];

int ff( int x ){
	return x == fa[x] ? x : fa[x] = ff(fa[x]);
}

void mg( int x, int y ){
	fa[ff(x)] = ff(y);	
}

int t;

int main(){

//	ios::sync_with_stdio(0);
//	cin.tie(0);
//	cout.tie(0);
	freopen(  ) 
	
	int n;
	n = read();

	for( int i = 1; i <= n; i++ )
		fa[i] = i;
	
	for( int i = 1; i <= n; i++ ){
		cin >> nxt[i];		
		mg( i,nxt[i] );
	}
	
	int ans = 1e9;
	
	for( int i = 1; i <= n; i++ ){
		if( !vis[fa[i]] ){
			int p = 0;
			vis[fa[i]] = 1;			
			int j = nxt[fa[i]];
			for( ; ; j = nxt[j] ){
				if( vis[j] ){
					p = j;
					break;
				}
				vis[j] = 1;
			} 
			int cnt = 0;
			j = p;
			do{
				cnt++;
				j = nxt[j];
			}
			while( j!=p );
			ans = min( ans,cnt );
		}	
		else
			continue;
	}
	
	cout << ans;		

	return 0;
}


2023/10/26 16:38
加载中...