zoukankan      html  css  js  c++  java
  • P1656 炸铁路

    题目:

    传送门

    题解思路:

    //大概题解思路:通过枚举的方式,在已知的m条道路中选出一条进行断开,相当于在建立道路联系的时候不将这条道路连上

    //然后连接剩余的道路(实质上进行m次这种操作  每次都有一条道路不连接)

    //误区:很容易被题目给带偏思路,会考虑先将所有的点通过道路连接,然后再选择炸毁,但不好实现的地方在于炸毁道路两边的点是有同一个祖先

    //如何对这些剩余的点重现建立新的祖先,因此我们把这部分归结到修建道路时不建立这条(重复进行m次操作)
     
    代码:
    #include<iostream>
    
    #include<algorithm>
    
    using namespace std;
    
    
    
    const int maxn=150+10;
    const int maxx=5000+10;
    
    int n,m;
    
    int a[maxn],b[maxn];
    
    int par[maxn];        //储存祖先结点
    
    int rank1[maxn];       //储存结点所在的高度
    
    // int inde=0;
    
    struct node{
    
        int a;
    
        int b;
    
    }temp[maxx];
    
    
    
    bool cmp(struct node tt,struct node kk){        //从小到大进行排序
    
        if(tt.a!=kk.a){         //先比较a 然后比较b
    
            return tt.a<kk.a;
    
        }else{
    
            return tt.b<kk.b;
    
        }
    
    }
    
    
    
    void init(){     //初始化
    
        for(int i=1;i<=n;i++){      //
    
            par[i]=i;
    
            rank1[i]=0;
    
        }
    
    }
    
    
    
    int find(int x){      //查找x祖先
    
        if(par[x]==x)  return x;        //如果x的祖先就是自己直接返回
    
        else return par[x]=find(par[x]);    //如果x的祖先不是自己 则需要通过find函数递归找到x的祖先 同时对x的父亲们也一起顺便找共同祖先
    
    }
    
    
    
    void unite(int x,int y){
    
        x=find(x);
    
        y=find(y);
    
    
    
        if(x==y)    return;
    
    
    
        if(rank1[x]>rank1[y]){
    
            par[y]=x;
    
        }else{
    
            par[x]=y;
    
            if(rank1[x]==rank1[y]){
    
                rank1[y]++;
    
            }
    
        }
    
    }
    
    
    
    bool same(int x,int y){
    
        if(find(x)==find(y))    return true;
    
        else return false;
    
    }
    
    
    
    int main(){
    
        cin>>n>>m;
    
        for(int i=1;i<=m;i++){
    
            int a,b;
    
            cin>>a>>b;
    
            if(a<=b){              //首先这些路的编号进行排序 方便后续直接输出
    
                temp[i].a=a;
    
                temp[i].b=b;
    
            }else{
    
                temp[i].a=b;
    
                temp[i].b=a;
    
            }
    
        }
    
    
    
        sort(temp+1,temp+m+1,cmp);
    
    
    
        for(int i=1;i<=m;i++){  //枚举m次
    
            init();
    
            for(int j=1;j<=m;j++){     //第i条道路不建立
    
                if(j!=i){
    
                    unite(temp[j].a,temp[j].b);       //道路连接
    
                }
    
            }
    
            //通过判断所有的par是否相同 相同即为有同一个祖先
    
            
    
            //或许可以不要下面代码
    
            int tt=0;
    
            for(int j=1;j<=n;j++){ //目标不是为了查询祖先  只是为了把所有的祖先进行建立
    
                tt=find(j);
    
            }
    
    
    
            int t=par[1];
    
            int flag=0;
    
            for(int j=2;j<=n;j++){
    
                if(t!=par[j]){          //代表有不同的祖先              
    
                    flag=1;
    
                    break;
    
                }
    
            }
    
    
    
            if(flag){      
    
                cout<<temp[i].a<<" "<<temp[i].b<<endl;
    
            }
    
        }
    
    
    
        return 0;
    
    }
  • 相关阅读:
    复利计算-做汉堡,结对2.0-复利计算再升级
    java集合
    java 封装,继承,多态基础
    购物车
    ajax
    演示
    实验四
    实验三
    构建之法6-7章读后感
    作业调度模拟程序
  • 原文地址:https://www.cnblogs.com/xwh-blogs/p/13799091.html
Copyright © 2011-2022 走看看