2023年码题杯 旅行 知识点:图论,并查集

120 阅读1分钟

码题集OJ-旅行 (matiji.net)

题解:码蹄集2023部分题目(第二弹)-CSDN博客

思想

用并查集

通过并查集统计一下是否所以点都可以从1到达,是否只有1不是到达点。

#include<bits/stdc++.h> 

using namespace std;
int n,m;
const int N=1e5+10;
int p[N],in[N];

int find(int x)
{
   if(x!=p[x])x=find(p[x]);
return p[x];
}
void merge(int a,int b)
{
    p[find(a)]=find(b);
}
void solve()
{
   cin>>n>>m;

    //初始化部分
    memset(p,0,sizeof p);
    memset(in,0,sizeof in);
    for(int i=0;i<n;i++)p[i]=i;
   
    //输入部分
      for(int i=0;i<m;i++)
   {
      int u,v;cin>>u>>v;
      merge(u,v);  //合并
      in[v]++;     //能到达v的道路数++
   }

   int count1=0,count0=0;  //入度为1的点的个数  入度为0的点的个数
   int flag=1;
   for(int i=1;i<=n;i++)
   {
    if(in[i]==0)count0++;  //起始点的入度为0,这里统计一下入度为0的点的个数,实际上就是专属起点部分
    else if(in[i]==1)count1++;  //意味着只有1条路到达我这里
    if(find(1)!=find(i))flag=0;  //意味着从1无法到达我这里
   }

   if(flag&&(count1==n-1&&count0==1))   //flag=1意味着从七十点可以到达任何点,那也就意味着可以从任意点到达另一个任意点
   {                                    //count1==n-1是表示入读为1的点有n-1个,缺的那个就是起点,起点没有入边,入度为0                                //count0=1表示入度为0的点只有1个,也就是起点
    cout<<"YES"<<endl;
   }
   else
   {
    cout<<"NO"<<endl;
   }
}
int main( )
{
    int t=1;cin>>t;
    while(t--)
    {
        solve();
    }
    return 0;
}

为什么上面代码中起点要特殊处理?

image.png