• PAT甲题题解-1013. Battle Over Cities (25)-求联通分支个数


    题目就是求联通分支个数
    删除一个点,剩下联通分支个数为cnt,那么需要建立cnt-1边才能把这cnt个联通分支个数求出来
    怎么求联通分支个数呢
    可以用并查集,但并查集的话复杂度是O(m*logn*k)
    我这里用的是dfs,dfs的复杂度只要O((m+n)*k)
    这里k是指因为有k个点要查询,每个都要求一下删除后的联通分支数。
    题目没给定m的范围,所以如果m很大的话,dfs时间会比较小。

    for一遍1~n个点,每次从一个未标记的点u开始dfs,标记该dfs中访问过的点。
    u未标记过,说明之前dfs的时候没访问过该点,即表明该点与前面的点不属于同一个分支,相当于新的分支。
    所以只要统计一下1~n中dfs多少次,就有多少个联通分支
    删除的点最开始标记一下,就不会访问到了。

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <string>
    #include <vector>
    #include <cstring>
    using namespace std;
    const int maxn=1000+5;
    int n,m,k;
    int check[maxn]; //先标记哪些点会check,防止有重复的点做重复的工作
    int ans[maxn]; //删掉节点i后剩余的连通分支数目
    int vis[maxn]; //用于dfs时候的标记
    struct Edge{
        int to;
        int next;
    }edge[maxn*maxn];
    int head[maxn];
    int tot;
    
    void init(){
        memset(head,-1,sizeof(head));
        tot=0;
    }
    void add(int u,int v){
        edge[tot].to=v;
        edge[tot].next=head[u];
        head[u]=tot++;
    }
    
    void dfs(int u){
        vis[u]=1;
        if(head[u]==-1)
            return;
        for(int k=head[u];k!=-1;k=edge[k].next){
            int v=edge[k].to;
            if(!vis[v]){
                dfs(v);
            }
        }
    }
    /*
    对于要check的点,求删除后的联通分支数,存储在ans数组里
    */
    void solve(){
        memset(ans,0,sizeof(ans));
        for(int i=1;i<=n;i++){
            //如果i是要被询问的
            if(check[i]){
                memset(vis,0,sizeof(vis));
                vis[i]=1;
                for(int j=1;j<=n;j++){
                    //每次有没被访问过的节点,表明又是一个新的联通分支
                    if(!vis[j] && j!=i){
                        dfs(j);
                        ans[i]++;
                    }
                }
            }
        }
    }
    int main()
    {
        int u,v;
        init();
        scanf("%d %d %d",&n,&m,&k);
        for(int i=0;i<m;i++){
            scanf("%d %d",&u,&v);
            add(u,v);
            add(v,u);
        }
        memset(check,0,sizeof(check));
        vector<int>query;
        for(int i=0;i<k;i++){
            scanf("%d",&u);
            check[u]=1;
            query.push_back(u);
        }
        solve();
        for(int i=0;i<query.size();i++){
            u=query[i];
            printf("%d
    ",ans[u]-1);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    H3C ER6300 + 两台 H3C S5120 组网举例
    H3C S5120-52P-WiNet交换机配置
    H3C S5120清除console口密码
    光纤简介
    Windows server 2008 R2 多用户远程桌面
    AutoIt 软件自动化操作
    windows server 2008 R2 计划任务备份系统
    AD域部署使用bginfo软件
    使用WSL吧
    Could not load file or assembly……
  • 原文地址:https://www.cnblogs.com/chenxiwenruo/p/6727990.html
Copyright © 2020-2023  润新知