• tyvj2044 旅游景点


    背景

    “扫地”杯III NOIP2012模拟赛 day2 第二题


    描述

    liouzhou_101住在柳侯公园附近,闲暇时刻都会去公园散散步。
    很那啥的就是,柳侯公园的道路太凌乱了,假若不认识路就会走着走着绕回原来的那条路。
    liouzhou_101就开始自己YY,假若给他当上那啥管理者,就会想尽量减少道路回圈的个数,但是大范围的改变道路终归不是什么良策。
    经过调查,发现公园有N个景点,为了显示景点之间的优越性,我们按照1,2,…,N来把这N个景点编号,当然编号越小就说明越重要。
    为了显示自己的英明决策,liouzhou_101决定,前K重要的景点最为重要,当然他们是标号为1…K了的。需要保证这K个景点不在任何一个环上,原因很简单,这前K个景点是很重要的景点,参观的人也很多,自然不会希望参观的人因为在兜圈子而迷路吧。
    于是,我们所能够做的就是把之前建造好的一些道路清除掉,使得保证前K重要的景点不在任何一个环上。


    输入格式

    第一行包括三个正整数N,M和K,N表示景点的数量,M表示公园里的路径条数,K表示前K个景点最为重要。
    再接下来M行,每行有两个正整数x和y,表示景点x和景点y之间有一条边。


    输出格式

    仅一行,输出至少去除多少条路径,使得前K个重要的景点不在任何一个环上。

    测试样例1

    输入

    11 13 5
    1 2
    1 3
    1 5
    3 5
    2 8
    4 11
    7 11
    6 10
    6 9
    2 3
    8 9
    5 9
    9 10

    输出

    3

    备注

    我们的删边方案是,删除(2,3)(5,9)(3,5)这三条边,这样节点1到5都不在任何一个环上。
    而且可知删除三条边已经是最少的了。

    30%的数据,满足N≤10,M≤20;
    60%的数据,满足N≤1,000,M≤10,000;
    100%的数据,满足N≤100,000,M≤200,000。
    注意:给出的无向图可能有重边和自环。


    Marek Cygan

    题目大意
    要求前k个点不在环上 至少删几条边
    题解
    并查集
    在kruskal算法当中,当这条边两个顶点的祖先相等时表示这两个点已经连通,再加入这条边就形成了环。
    我们依次加边,加入这条边会形成环(即边的两个顶点已经连通)并且两个顶点存在编号小于k时,删去这条边。
    然鹅 这是不对的,如果加入一条边形成环但边的顶点大于k 但是小于k的点却在这个环中,却要删去这条边。我们
    可以先加入顶点大于k的边 最后再加顶点小于k的边。MMP我给点的编号从大到小排了个序依次加入就都WA了,╭(╯^╰)╮
    代码
    AC
    #include<iostream>
    #include<cstdio>
    #define maxn 100005
    using namespace std;
    
    int n,m,k,x,y,cnt,ans,fa[maxn];
    struct Edge{
        int x,y;
    }edge[maxn<<1];
     
    int read(){
        int x=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
        return x*f;
    }
     
    int f(int x){
        return fa[x]==x?x:fa[x]=f(fa[x]);
    }
     
    int main(){
        n=read();m=read();k=read();
        for(int i=1;i<=n;i++)fa[i]=i;
        for(int i=1;i<=m;i++){
            x=read();y=read();
            if(x>k&&y>k){
                int fx=f(x),fy=f(y);
                if(fx!=fy)fa[fx]=fy;
            }else
            edge[++cnt].x=x,edge[cnt].y=y;
        }
        for(int i=1;i<=cnt;i++){
            int fx=f(edge[i].x),fy=f(edge[i].y);
            if(fx==fy)ans++;
            else fa[fx]=fy;
        }
        printf("%d
    ",ans);
        return 0;
    }
  • 相关阅读:
    企业应用架构研究系列三:应用系统集成
    企业应用架构研究系列十九:Docker开发环境
    企业应用架构研究系列二十:创建&发布Docker
    前端NEXT实践系列:(一)ECMAScript 6.0技术栈
    企业应用架构研究系列二十七:Vue3.0 之环境的搭建与Vue Antd Admin探索
    企业应用架构研究系列五:极限编程(XP)& 敏捷管理(Scrum)
    记一次HIV初筛假阳性的经历
    C#发送邮件
    Ubuntu允许root登录
    lerna学习
  • 原文地址:https://www.cnblogs.com/zzyh/p/7444395.html
Copyright © 2020-2023  润新知