每日一题 - 231102 - K. Link-Cut Tree

这篇文章介绍了如何使用C++实现K.Link-CutTree数据结构,并结合邻接表和BreadthFirstSearch(BFS)算法解决特定图问题。代码展示了初始化、添加边、查找父节点以及使用BFS遍历的过程。
//
#include<bits/stdc++.h>
using namespace std;
//#define int long long

const int N=1e5+6;
const int M=N<<1;
int h[N],idx;
struct A{ int y,data,next; }e[M];
int n,m;

struct B{ int x,y,data; }in[M];

int dad[N+5];
int d[N+5];
bool used[N+5];

void init()
{
	for( int i=1;i<=n;i++ ) dad[i]=i;
	
	memset( h,-1,sizeof( h ) );
	idx=0;										//
	 
	memset( d,0,sizeof( d ) );					//
	memset( used,0,sizeof( used ) );
}

int get_dad( int x )
{
	return dad[x] = dad[x]==x ? x : get_dad( dad[x] );
}

void add( int x,int y,int data )
{
	e[idx]=(A){ y,data,h[x] };
	h[x]=idx++;
}

void bfs()
{
	queue<int> q;
	
	for( int i=1;i<=n;i++ )
		if( d[i]==1 ) q.push(i);
		
//	cout<<"q.size()="<<q.size()<<endl;
//	
//	cout<<"d[]: ";
//	for( int i=1;i<=n;i++ ) printf("%d ",d[i] );
//	cout<<endl;
	
	while( !q.empty() )
	{
		int x=q.front(); q.pop();
		
		for( int i=h[x];~i;i=e[i].next )
		{
			int y=e[i].y;
			int data=e[i].data;
			
			used[data]=1;
			d[y]--;
			if( d[y]==1 ) q.push(y);
		}
	}
}

void solve()
{
	int t;
	
	scanf("%d",&t );
	while( t-- )
	{
		scanf("%d%d",&n,&m );
		
		init();
		for( int i=1;i<=m;i++ )
		{
			int x,y,data=i;
			scanf("%d%d",&x,&y );
			in[i]=(B){ x,y,data };
		}
		
		int maxx=0;
		for( int i=1;i<=m;i++ )
		{
			int tx=get_dad( in[i].x );
			int ty=get_dad( in[i].y );
			
//			cout<<"tx="<<tx<<" "<<"ty="<<ty<<endl;
			
			if( tx==ty )
			{
				maxx=i;
				for( int j=1;j<=i;j++ )
				{
					int x=in[j].x;				//
					int y=in[j].y;
					int data=in[j].data;
					
					add( x,y,data );
					add( y,x,data );
					d[x]++,d[y]++;
				}
				bfs();
				break;
			}
			else dad[tx]=ty;
		}
		
		if( maxx )
		{
			vector<int> v;
			for( int i=1;i<=maxx;i++ )
				if( used[i]==0 ) v.push_back( i );
				
			for( int i=0;i<v.size();i++ )
			{
				if( i ) putchar(' ');
				printf("%d",v[i] );
			}
		}
		else printf("-1");
		
		putchar('\n');
	}
}

signed main()
{
	solve();
	return 0;
}

作者 | 乐意奥AI

评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值