zoukankan      html  css  js  c++  java
  • PAT-1013 Battle Over Cities (25)

    求解连通性问题,最好用的当然是并查集了,可以使用深搜或者广搜。

    这道题目的意思是给定一些道路,如果把其中一个顶点去掉,那么需要建立多少条道路才能联通所有顶点。

    这道题目如果用朴素的并查集的话第四个测试用例会超时,因此想到带路径压缩的并查集。递归或者非递归方式都可以,对于这道题目来说不会差别很大,不过用递归可能会有栈溢出的问题,当数据量小的时候没有什么大问题。(其实递归的深度不会很大,所以RE得风险应该很小的,已建立起来的数目只有两层。错误,比如两个帮派老大带了一群小弟,一个帮派老大投靠了另外一个小弟,那么就会出现三层的情况,并不是说并查集就是一定是两层的,可能会有多个两层合在一起,那么就出现三层了)

    #include<stdio.h>
    #include<stdlib.h>
    
    
    #define MAX 1010
    
    struct Edge
    {
       int a;
       int b;
    }edge[MAX*MAX];
    
    int father[MAX];
    
    void init(int n)
    {
        for(int i=1;i<=n;i++)
           father[i]=i;
    }
    
    void output(int n)
    {
        for(int i=1;i<=n;i++)
           printf("%d ",father[i]);
    }
    
    int findFather(int x)
    {
        while(x!=father[x])
           x=father[x];
        return x; 
    }
    int findFatherWithCompress(int x)//4    答案正确    119     4216    4/4  递归寻找父亲节点,然后把节点挂载到父亲节点上 
    {
        if(x!=father[x])
          father[x]=findFatherWithCompress(father[x]);
        return father[x];
    }
    
    int findFatherWithCompress2(int x)//开始先找到x的父亲节点,此时并未压缩,然后沿着x-->father[x]一直压缩路径,把节点直接赋值给最顶层的父亲节点 
    {
        int r=x;
        while(r!=father[r])
            r=father[r];
        int k=x;
        while(father[k]!=r)
        { 
          int j=father[k];//j exchange for father[k] 
          father[k]=r;
          k=j;
         }
         return r;
    }
    void merge(int a,int b)
    {
       int x=findFatherWithCompress2(a);
       int y=findFatherWithCompress2(b);
       if(x!=y)
         father[x]=y; //find father and merger them 
    }
    int main()
    { 
        int n,m,k;
        freopen("1013-in.txt","r",stdin);
        freopen("1013-out.txt","w",stdout);
        
        while(scanf("%d%d%d",&n,&m,&k)!=EOF)
        {
        
        for(int i=0;i<m;i++)
          scanf("%d%d",&edge[i].a,&edge[i].b);
        
        for(int j=0;j<k;j++)
        {
           init(n);
           int c,a,b;
           scanf("%d",&c);
           for(int i=0;i<m;i++)
           {
              a=edge[i].a;
              b=edge[i].b;
              if(a==c||b==c)
                 continue;
              merge(a,b);
           }
           int count=0;
           //output(n);
           for(int i=1;i<=n;i++)
           {
              if(father[i]==i)
              {
                 count++;
              }
           }
           printf("%d
    ",count-2);//except the city 
        }
        
       }
        return 0;
    } 
  • 相关阅读:
    linux 命令
    http 协议
    关于 yaf路由
    yaf学习 从头开始
    插件概念
    框架与设计模式的区别
    一个程序员的创业(爱情)故事
    话说那年微信接口平台创业旧事
    推荐sinaapp谷歌搜索引擎,firefox自定义搜索引擎
    新的开源java反汇编程序Procyon
  • 原文地址:https://www.cnblogs.com/championlai/p/3982288.html
Copyright © 2011-2022 走看看