//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几乎一样,不写了