zoukankan      html  css  js  c++  java
  • PAT A1013 Battle Over Cities (25分)


    图的实现方式主要有两种:1.邻接表 2.邻接矩阵
    邻接矩阵在顶点数目大于1000的情况就基本不适用了,而邻接表的链表实现在考试中代码量偏大
    所以采取变成数组构建邻接表可以简化程序书写
    邻接表的表示为:vector G[N];
    当然本题还可以利用并查集的数据结构完成快速合并与查询,见代码2,但其实不建议使用并查集,因为并查集虽然容易确定是否连通但是最大的缺点就是很难删除,为了完成删除k次的操作
    只能在每次查询阶段建立并查集,没有DFS和BFS来的简便和明显
    注意:

    1. 使用并查集必须进行路径压缩否则会导致数据超时
    2. 由于是无向图,在读入数据两个方向的边都需要存储
      代码1:邻接表+DFS
    #include <cstdio>
    #include <vector>
    #include <string.h>
    using namespace std;
    const int N = 1010;
    vector<int> G[N];//从1开始
    bool vis[N];//从1开始
    
    void DFS(int a,int check){
        if(a==check||vis[a]==true) return;
        else{
            vis[a] = true;
            for(int i = 0;i<G[a].size();i++){
                    DFS(G[a][i],check);
            }
            return;
        }
    }
    int main(){
        int n,m,k;
        scanf("%d%d%d",&n,&m,&k);
        for(int i = 0;i< m;i++){
            int a,b;
            scanf("%d%d",&a,&b);
            G[a].push_back(b);
            G[b].push_back(a);
        }
        int check;
        for(int i = 0 ; i < k;i++){//k次查询
            scanf("%d",&check);
            memset(vis,false,sizeof(vis));
            int block = 0;//连通块个数
            for(int j = 1; j <= n;j++){
                if(j!=check&&vis[j]==false){
                    DFS(j,check);
                    block++;
                }
            }
            printf("%d",block-1);
                
            if(i < k-1) printf("
    ");
        }
        return 0;
    }
    

    代码2:邻接表+并查集

    #include <cstdio>
    #include <vector>
    #include <string.h>
    using namespace std;
    const int N = 1010;
    vector<int> G[N];//从1开始
    bool vis[N];//从1开始
    int father[N];//从1开始
    
    void init(int n){//从1到n
        for(int i = 1;i<=n;i++){
            father[i] = i;
            vis[i] = false;
        }
        return;
    }
    
    int findFather(int x){
        int a = x;
        while(x!=father[x]){
            x = father[x];
        }
        //路径压缩
        while(a!=father[a]){
            int z = a;
            a = father[a];
            father[z] = x;
        }
        return x;
    }
    
    void Union(int a,int b){
        int fa = findFather(a);
        int fb = findFather(b);
        if(fa!=fb) father[fa] = fb;
        return;
    }
    int main(){
        int n,m,k;
        scanf("%d%d%d",&n,&m,&k);
        for(int i = 0;i< m;i++){
            int a,b;
            scanf("%d%d",&a,&b);
            G[a].push_back(b);
            G[b].push_back(a);
        }
        int check;
        for(int i = 0 ; i < k;i++){//k次查询
            scanf("%d",&check);
            init(n);
            //建立当前并查集
            for(int j = 1; j <= n;j++){
                if(j!=check){
                    for(int d = 0;d<G[j].size();d++){
                        if(G[j][d]!=check){
                            int v = G[j][d];
                            int u = j; 
                            Union(v,u);
                        }
                    }
                }                
            }
            int block = 0;//连通块个数
            for(int j = 1;j <= n;j++){//遍历n个结点
                if(j != check){
                    int fa = findFather(j);
                    if(vis[fa]==false){
                        block++;
                        vis[fa] = true;
                    }
                }
            }
            
            printf("%d",block-1);
                
            if(i < k-1) printf("
    ");
       }
            
            
        
        return 0;
    }
    
  • 相关阅读:
    使用批处理bat作为日期系统日期的前三天
    电脑桌面显示倒退
    BZOJ 2648/2716(SJY把件-KD_Tree)[Template:KD_Tree]
    yii使用寻呼功能
    宝付额度
    vs2010旗舰版产品密钥
    考察网贷平台是否正规,仅供参考。
    sql server 修改字段大小
    帕累托分析法
    帕累托分析法(Pareto Analysis)(柏拉图分析)
  • 原文地址:https://www.cnblogs.com/shuibeng/p/13572003.html
Copyright © 2011-2022 走看看