求解树中节点的距离:tarjan离线算法、转化为Floyd无向图、BFS、DFS

//LCA离线算法 ,注意了,输出肯定是无序的! 
//顺序查找只能在主函数里面再定义,注意while内的初始化问题啊! 
/*
6 5
1 2
1 3
2 4
2 6
3 5
3
1 5
4 6
3 5
*/
#include <bits/stdc++.h>
using namespace std;
const int MAXN=100;
vector<int>Tree[MAXN];
vector<int>Query[MAXN];
int father[MAXN];
int height[MAXN];
int Indegree[MAXN];
int visit[MAXN];
int ancestor[MAXN];

void Initial(int n)
{
	for(int i=0;i<=n;i++)//编号从1开始 
	{
		father[i]=i;
		height[i]=0;
		Indegree[i]=0; 
		Tree[i].clear();
		Query[i].clear();
		visit[i]=0;
		ancestor[i]=0;	
	}
	return ;
}

int Find(int x)
{
	if(x==father[x]) return x;
	else return Find(father[x]);
 } 

void Union(int x,int y)
{
	x=Find(x);
	y=Find(y);
	if(x!=y)
	{
		if(height[x]>height[y])
		{
			father[y]=x;
			height[x]++;
		}
		if(height[y]>height[x])
		{
			father[x]=y;
			height[y]++;
		}
		else father[y]=x;
	}
	return ;
}

void Tarjan(int x)
{
	ancestor[x]=x;//标记祖先最重要了 
	for(int i=0;i<Tree[x].size();i++)
	{
		Tarjan(Tree[x][i]);
		Union(x,Tree[x][i]);
		ancestor[Find(x)]=x;//因为并查集的压缩路径,x是根节点,注意保存! 
	}
	visit[x]=1;//邻居已经访问
	for(int i=0;i<Query[x].size();i++)
	{
		if(visit[Query[x][i]]==1)
		{
			printf("%d与%d的公共祖先是%d\n",x,Query[x][i],ancestor[Find(Query[x][i])]);//都被访问,注意:这是无序输出,改有序可在主函数的查询中修改,主要是初始化别漏了
		}
	 } 
	 return ;
}

int main()
{
	int n,m;
	while(cin>>n>>m)//编号还是从 1 开始的. 
	{
		Initial(n);
		while(m--)
		{
			int a,b;
			cin>>a>>b;
			Tree[a].push_back(b);
			Indegree[b]++;
		}
		int k;
		scanf("%d",&k);
		while(k--)
		{
			int x,y;
			scanf("%d%d",&x,&y);
			Query[x].push_back(y);
			Query[y].push_back(x);
		}
		for(int i=1;i<n;i++)//因为编号是1,所以必须从1开始!因为本体恰好i=0时是满足的! 
		{
			if(Indegree[i]==0)
			{
				Tarjan(i);
				break;
			}
		}
	}
	return 0;
} 

Floyd 解法

//1
//8 4
//2 3
//4 5
//6 -1
//-1 -1
//-1 7
//-1 -1
//8 -1
//-1 -1

//1 6
//4 6
//4 5
//8 1
//输出样例: 
//2
//4
//2
//4
#include <bits/stdc++.h>
using namespace std;
const int MAXN=100;
const int INF=INT_MAX;
int dis[MAXN][MAXN];
int g[MAXN][MAXN];
int Add(int x,int y)//防止出现溢出
{
	if(x==INF||y==INF) return INF;
	else return x+y;
}

int Add2(int x,int y,int z)
{
	if(x==INF||y==INF||z==INF) return INF;
	else return x+y+z;
}

int main()
{
	int casenumber;
	scanf("%d",&casenumber);
	while(casenumber--)
	{
		for(int i=0;i<MAXN;i++)
		{
			for(int j=0;j<MAXN;j++)
			{
				dis[i][j]=INF;
			}
			dis[i][i]=0;
		}
		int n,m;
		scanf("%d%d",&n,&m);
		for(int i=1;i<=n;i++)
		{
			int p,q;
			scanf("%d%d",&p,&q);
			if(p!=-1) 
			{
				dis[p][i]=dis[i][p]=1;
			}
			if(q!=-1) 
			{
				dis[q][i]=dis[i][q]=1;	
			}
		}
		for(int k=1;k<=n;k++)
		{
			for(int i=1;i<=n;i++)
			{
				for(int j=i;j<=n;j++)
				{
					if(dis[i][j]>Add(dis[i][k],dis[k][j])) 
					{
						dis[i][j]=dis[j][i]=Add(dis[i][k],dis[k][j]);
					}
				}
			}
		}
		while(m--)
		{
			int x,y;
			scanf("%d%d",&x,&y);
			cout<<dis[x][y]<<endl;
		}
	}
	return 0;
}
//BFS求树中每点的距离 
/*
1
8 4
2 3
4 5
6 -1
-1 -1
-1 7
-1 -1
8 -1
-1 -1
1 6
4 6
4 5
8 1
*/
#include <bits/stdc++.h>
using namespace std;
bool visit[1000];
struct Point{
	int num;
	int level;
	Point(int n,int l):num(n),level(l){}
};

vector<int>graph[100];
int maximum=0;
void BFS(int x,int y)
{
	memset(visit,false,sizeof(visit));
	int level=0;
	queue<Point>myqueue;
	myqueue.push(Point(x,level));
	visit[x]=true;
	while(!myqueue.empty())
	{
		Point current=myqueue.front();
		myqueue.pop();
		if(current.num==y) 
		{
			cout<<current.level<<endl;;		
			return ;
		}
		for(int i=0;i<graph[current.num].size();i++)
		{
			Point next(current.num,current.level+1); 
			next.num=graph[current.num][i];
			if(visit[next.num]==true) continue; 
			myqueue.push(next);
			visit[next.num]=true;
		}				
	}
	return ;
}

int main()
{
	int T; 
	cin>>T;
	while(T--)
	{
		memset(graph,0,sizeof(graph));
		int n,m;
		cin>>n>>m;
		for(int i=1;i<=n;i++)
		{
			int a,b;
			cin>>a>>b; 
			if(a!=-1)
			{
				graph[i].push_back(a);
				graph[a].push_back(i);
			}
			if(b!=-1) 
			{
				graph[i].push_back(b);
				graph[b].push_back(i);
			}
		}
		while(m--) 
		{
			int a,b;
			scanf("%d%d",&a,&b);
			BFS(a,b);
		}
	} 
	return 0;
}

DFS和BFS几乎一样,不写了

发布了8 篇原创文章 · 获赞 0 · 访问量 69

猜你喜欢

转载自blog.csdn.net/weixin_46274692/article/details/105031952
今日推荐