算法笔记-图搜索

统计图的连通分支数

思路 建图,搜索,注意这种建图方式是有向图,

反例: 1 2,3 4,4 1这种不会识别出来,因此建图时需要使用有向图,在add阶段加入两个方向的路径;

add时从1开始的边的标号,0用来判断结束,斗则冲突有问题

int tot=0;
const int maxn=1e6;
int nxt[maxn]={0},head[maxn]={0},u[maxn]={0},v[maxn]={0};
int vis[maxn]={0};

void add(int i,int j){
    tot++;
    nxt[tot]=head[i];
    head[i]=tot;
    u[tot]=i;
    v[tot]=j;
    
}
int main(){
    int x,y;
    while (cin>>x>>y)
    {
        add(x,y);//双向
        add(y,x);
    }
    // 1 2 /3 4/  4 1如果不是双向这种就不行
    int ans=0;
    for(int i=1;i<=tot;i++){
        // cout<<"i:"<<i<<"\n";
        if(vis[i]) continue;
        ans++;
        // vis[i]=1;
        queue<int>q;
        q.push(u[i]);
        while (q.size())
        {
            int nowp=q.front();
            q.pop();
            for(int num=head[nowp];num;num=nxt[num]){
                if(vis[num]){
                    continue;
                }
                vis[num]=1;
                q.push(v[num]);
            }
        }
        
    }
    cout<<ans<<"\n";
    return 0;
}

问题 B: 连通图

给定一个无向图和其中的所有边,判断这个图是否所有顶点都是连通的。

**思路:**和上题思路一样;注意细节:每次都全部初始化化为0;

vis数组表示的是某个边是否访问过

const int maxn=1e5;
int head[maxn]={0},u[maxn]={0},v[maxn]={0},vis[maxn],nxt[maxn];
int tot=0;//vis点为是否进入过队列
int nodes[maxn];//访问过的节点
void add(int x,int y){
    tot++;
    nxt[tot]=head[x];
    head[x]=tot;
    u[tot]=x;
    v[tot]=y;
}
int main(){
    int n,m;
    while (cin>>n>>m)
    {
        tot=0;
        memset(vis,0,maxn);
        memset(head,0,maxn);
        memset(nodes,0,maxn);
        memset(nxt,0,maxn);
        memset(v,0,maxn);
        memset(u,0,maxn);
        if(n==0) break;
        int x,y;
        while (m--)
        {
            cin>>x>>y;
            add(x,y);
            add(y,x);
        }
        queue<int>q;
        q.push(u[1]); //node
        while (q.size())
        {
            int now=q.front();
            q.pop();
            for(int i=head[now];i;i=nxt[i]){
                if(vis[i]==0){
                    vis[i]=1;
                    nodes[u[i]]=1;
                    nodes[v[i]]=1;
                    q.push(v[i]);
                }
            }
        }
        bool flag=true;
        for(int i=1;i<=n;i++){
            if(nodes[i]==0){
                flag=false;
                break;
            }
        }
        if(flag) cout<<"YES\n";
        else cout<<"NO\n";
    }   
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值