Connected Components-连通分量(挑战程序设计竞赛)

题目:

请编写一个程序,输入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;
}

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,以下是代码形式的电话线路图状态: ``` @startuml title Telephone State Diagram [*] --> Idle : Initial State Idle --> Dialing : Off Hook Event Dialing --> Connecting : Valid Number Event Dialing --> Disconnected : Invalid/Wrong Number Event Connecting --> TimeOut : Timeout Event Connecting --> Connected : Called Phone Answers Event Ringing --> Connected : Called Phone Answers Event Connected --> Idle : On Hook Event Connected --> Busy Tone : Line Busy Event Connected --> TimeOut : Timeout Event Connected --> Disconnected : Timeout Event Connected --> Ringing : Play Message Event @enduml ``` 解释一下: - 初始状态为空闲状态(`[*] --> Idle : Initial State`)。 - 当电话机摘机时,电话状态从空闲状态转入拨号状态(`Idle --> Dialing : Off Hook Event`)。 - 当拨号有效号码时,电话状态从拨号状态转入连接状态(`Dialing --> Connecting : Valid Number Event`)。 - 当拨号号码无效或错误时,电话状态从拨号状态转入未连接状态(`Dialing --> Disconnected : Invalid/Wrong Number Event`)。 - 当连接超时时,电话连接状态从连接状态转入超时状态(`Connecting --> TimeOut : Timeout Event`)。 - 当被拨打的电话接听时,电话连接状态从连接状态或响铃状态转入已连接状态(`Connecting --> Connected : Called Phone Answers Event` 或 `Ringing --> Connected : Called Phone Answers Event`)。 - 当已连接状态的电话机挂机时,电话状态从已连接状态转入空闲状态(`Connected --> Idle : On Hook Event`)。 - 当已连接状态的电话线路忙碌时,电话状态从已连接状态转入忙音状态(`Connected --> Busy Tone : Line Busy Event`)。 - 当已连接状态的电话连接超时时,电话状态从已连接状态转入未连接状态(`Connected --> TimeOut : Timeout Event`)。 - 当已连接状态的电话播放信息时,电话状态从已连接状态转入响铃状态(`Connected --> Ringing : Play Message Event`)。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值