zoukankan      html  css  js  c++  java
  • D. Dogeforces 题解(并查集+构造)

    题目链接

    题目大意

    要你构造一棵树

    给你所有树的叶子,数目为n

    并且告诉你所有叶子的lca所代表的权值

    且祖宗节点的权值必定比儿子节点的权值大

    题目思路

    参考代码:https://blog.csdn.net/liufengwei1/article/details/114298063

    就是并查集模拟

    因为祖宗比儿子大,把a\([i][j]\)从小到大排序,然后从下往上构造了,要利用并查集模拟

    而且排序的时候还要按照i排序

    原因

    比如1 2 3 4都是父亲是5,但是你在排序的时候搞出了1 2父亲是5,然后处理3 4,发现他们的父节点都是他们自己,所以搞出个新节点父亲6,最后发现1,3的父亲还是权值和5,6一样,就会出问题,相当于多创建了一个点,但如果一开始排序就先 1 2 ,1 3,1 4,就会只有一个父亲5

    代码

    #include<bits/stdc++.h>
    using namespace std;
    #define fi first
    #define se second
    typedef long long ll;
    typedef pair<double,int> pdi;
    const ll INF=0x3f3f3f3f3f3f3f3f;
    const int maxn=500+5,mod=1e7;
    int n,m;
    int fa[maxn*maxn];
    int a[maxn][maxn];
    int v[maxn*maxn];
    int c[maxn*maxn];
    struct edge{
        int l,r,val;
    }e[maxn*maxn];
    pair<int,int> ans[maxn*maxn];
    int find(int x){
        return x==fa[x]?x:fa[x]=find(fa[x]);
    }
    bool cmp(edge a,edge b){
        if(a.val!=b.val){
            return a.val<b .val;
        }else {
            return a.l<b.l;
        }
    }
    int main(){
        scanf("%d",&n);
        for(int i=1;i<=n;i++){
            for(int j=1;j<=n;j++){
                scanf("%d",&a[i][j]);
                e[i+(j-1)*n]={i,j,a[i][j]};
            }
        }
        m=n;
        for(int i=1;i<=n;i++){
            fa[i]=i;
            c[i]=a[i][i];
        }
        sort(e+1,e+1+n*n,cmp);
        int cnt=0;
        for(int i=1;i<=n*n;i++){
            int x=find(e[i].l),y=find(e[i].r);
            if(x==y) continue;
            if(c[x]==e[i].val){
                fa[y]=x;
                ans[++cnt]={y,x};
            }else if(c[y]==e[i].val){
                fa[x]=y;
                ans[++cnt]={x,y};
            }else{
                fa[x]=fa[y]=++m;
                fa[m]=m;
                c[m]=e[i].val;
                ans[++cnt]={x,m};
                ans[++cnt]={y,m};
            }
        }
        printf("%d\n",m);
        for(int i=1;i<=m;i++){
            printf("%d ",c[i]);
        }
        printf("\n%d\n",find(1));
        for(int i=1;i<=cnt;i++){
            printf("%d %d\n",ans[i].fi,ans[i].se);
        }
        return 0;
    }
    
    
    不摆烂了,写题
  • 相关阅读:
    命令行编译运行java工程(转)
    JAVA配置环境变量的意义(转)
    在Linux环境下搭建Tomcat+mysql+jdk环境(转)
    java环境变量
    varchar(8000) nvarchar(4000) varchar(max) nvarchar(max) 区别
    HTTP与HTTPS握手的那些事(转载)
    ELK研究-部署搭建运用
    主机规划与磁盘分区
    占位符问题 python pymysql
    django 数据迁移的问题 sqlite3 --> mysql
  • 原文地址:https://www.cnblogs.com/hunxuewangzi/p/14475065.html
Copyright © 2011-2022 走看看