题目:
请编写一个程序,输入SNS的朋友关系,判断从指定人物出发能否通过双向朋友链抵达人物。
输入: 第1行输入代表SNS用户数的整数n以及代表朋友关系数的m,用空格隔开。SNS各用户的ID分别为0到n-1。
接下来的m行输入朋友关系,每个朋友关系占1行。1个朋友关系包含s、t这两个整数,表示s和t为朋友。s、t输入时用空格隔开。
紧接下来的1行输入问题数q。再接下来的q行输入问题。
各问题均为用空格隔开的2个整数s、t,表示从s出发能否抵达t?
输出: 如果从s出发能抵达t就输出yes,否则输出no,每个问题的回答占1行。
限制:
2 ≤ n ≤ 100000
0 ≤ m ≤ 100000
1 ≤ q ≤ 10000
输入示例
10 9
0 1
0 2
3 4
5 7
5 6
6 7
6 8
7 8
8 9
3
0 1
5 9
1 3
输出示例
yes
yes
no
解题思路:
这道题是求连通分量,我们可以将不连通图分为多个极大连通子图也就是连通分量,我们可以将图的连通分量进行染色操作,将在一个连通分量的子图染为同一种颜色,然后直接判断color[x]==color[y]即可
如何染色?
我们利用图的dfs,在遍历的过程中进行染色。这道题的dfs是利用栈完成,每一次从一个结点出发压入栈,在依次遍历于该节点有关系的其他结点。
图的描述
这道题由于n=100000,如果用邻接矩阵,要开空间为10^10的二维数组过于庞大,所以我们用邻接表,开100000个vector即可。
代码实现:
#include <bits/stdc++.h>
using namespace std;
const int maxn=100010;
int n,k;
vector<int> G[maxn];//使用邻接表
int color[maxn];
void dfs()
{
stack<int> s;
int id=1;
memset(color,-1,sizeof(color));//初始化颜色
//从u结点开始dfs
for(int u=0; u<n; u++)
{
if(color[u]==-1)//如果u结点没有颜色
{
s.push(u);
color[u]=id;
while(!s.empty())
{
int t=s.top();
s.pop();
//将与t有关系的结点全部压入栈
for(int i=0; i<G[t].size(); i++)
{
int v=G[t][i];
if(color[v]==-1)
{
color[v]=id;
s.push(G[t][i]);
}
}
}
id++;//颜色++
}
}
}
int main()
{
scanf("%d%d",&n,&k);//读入n个结点,k个关系
int x,y;
for(int i=1; i<=k; i++)
{
cin>>x>>y;
G[x].push_back(y);
G[y].push_back(x);
}
dfs();//深搜染色
int q;
scanf("%d",&q);//读入判断关系组数量
for(int i=1; i<=q; i++)
{
cin>>x>>y;
printf("%s\n",color[x]==color[y]?"Yes":"No");//三元表达式
}
return 0;
}