Educational Codeforces Round 105 (Rated for Div. 2) D题-Dogeforces(构造+并查集)

题意:

构造一棵树,现给出叶子节点的个数,以及两两叶子节点的 L C A LCA LCA 的权值,要求除了叶子节点,每个点都有至少有两个儿子节点,且父亲节点的权值一定比儿子节点的权值大。

题解:

因为上层权值一定比下层权值大,所以可以先按照权值排序,然后依次从底层往上构造。具体怎么构造呢?

我们用 f a [ i ] fa[i] fa[i] 数组记录当前 i 节点的最前的祖先,用并查集维护一下,然后会存在如下几种情况:

1: f a [ x ] ! = f a [ y ] fa[x]!=fa[y] fa[x]!=fa[y]

( 1 ) (1) (1) a [ x ] [ y ] ! = v a l [ f a [ x ] ] a[x][y]!=val[fa[x]] a[x][y]!=val[fa[x]] && a [ x ] [ y ] ! = v a l [ f a [ y ] ] a[x][y]!=val[fa[y]] a[x][y]!=val[fa[y]] ,那么说明我们需要加入一个点作为 f a [ x ] fa[x] fa[x] f a [ y ] fa[y] fa[y]的父亲节点。

( 2 ) (2) (2) a [ x ] [ y ] = = v a l [ f a [ x ] ] a[x][y]==val[fa[x]] a[x][y]==val[fa[x]] && a [ x ] [ y ] ! = v a l [ f a [ y ] ] a[x][y]!=val[fa[y]] a[x][y]!=val[fa[y]] ,那么说明 x x x y y y l c a lca lca 就是 f a [ x ] fa[x] fa[x]

( 3 ) (3) (3) a [ x ] [ y ] ! = v a l [ f a [ x ] ] a[x][y]!=val[fa[x]] a[x][y]!=val[fa[x]] && a [ x ] [ y ] = = v a l [ f a [ y ] ] a[x][y]==val[fa[y]] a[x][y]==val[fa[y]] ,同上。

2: f a [ x ] = = f a [ y ] fa[x]==fa[y] fa[x]==fa[y]

这种情况直接 c o n t i n u e continue continue

我并没有写 a [ x ] [ y ] = = v a l [ f a [ x ] ] a[x][y]==val[fa[x]] a[x][y]==val[fa[x]] && a [ x ] [ y ] = = v a l [ f a [ y ] ] a[x][y]==val[fa[y]] a[x][y]==val[fa[y]] 这种情况,因为它属于第二类,但是如果处理不当,这里会是一个坑点。举个例子:
在这里插入图片描述
假如先处理点1和2 ,再处理点3和点4,那么会发现构造出来的父亲节点的权值是和儿子节点一样的,所以要先把其中一个点全部处理完,即在排序时,假如权值相等,按照节点编号大小排序,这样就可以避免这种情况。
(因为这个坑wa了好多发,o(╥﹏╥)o )

代码:

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#include<map>
#include<stack>
#include<set>
#include<ctime>
#define iss ios::sync_with_stdio(false)
using namespace std;
typedef unsigned long long ull;
typedef long long ll;
typedef pair<int,int>pii;
const int MAXN=1e6+500;
const int mod=1e9+7;
const int inf=0x3f3f3f3f;
int a[505][505];
int fa[MAXN];
int b[MAXN];
struct node
{
    int x,y;
    int val;
}f[MAXN];
bool cmp(node q1,node q2)
{
    if(q1.val==q2.val){
       if(q1.x==q2.x){
        return q1.y<q2.y;
       } 
       else return q1.x<q2.x;
    }
    else return q1.val<q2.val;
}
struct Node
{
    int to;
    int next;
}e[MAXN<<1];
int cnt=0;
int head[MAXN];
void add(int u,int v)
{
    e[cnt].to=v;
    e[cnt].next=head[u];
    head[u]=cnt++;
}
int finder(int x)
{
    if(fa[x]==x) return x;
    else return fa[x]=finder(fa[x]);
}
void dfs(int u,int f)
{   
    //cout<<u<<endl;
    for(int i=head[u];i!=-1;i=e[i].next){
        int v=e[i].to;
        if(v==f) continue;   
        dfs(v,u);
        printf("%d %d\n",v,u);
    }
}
int main(){
    for(int i=1;i<MAXN;i++){
        fa[i]=i;
        head[i]=-1;
    }
    int n;
    cin>>n;
    int tot=0;
    int m=0;
    for(int i=1;i<=n;i++){
        for(int j=1;j<=n;j++){
            cin>>a[i][j];
            if(i>j) continue;
            if(i==j){
                b[++tot]=a[i][j];
            }
            else{
                f[++m].x=i;
                f[m].y=j;
                f[m].val=a[i][j];
            }
        }
    }
    sort(f+1,f+1+m,cmp);
    for(int i=1;i<=m;i++){
        int x=f[i].x;
        int y=f[i].y;
        int val=f[i].val;
        int fa_x=finder(x);
        int fa_y=finder(y);
        if(fa_x==fa_y) continue;
        if(val==b[fa_x]){
            add(fa_x,fa_y);
            add(fa_y,fa_x);
            //cout<<fa_x<<" "<<fa_y<<endl;
            fa[fa_y]=fa_x;
        }
        else if(val==b[fa_y]){
            add(fa_x,fa_y);
            add(fa_y,fa_x);
            //cout<<fa_x<<" "<<fa_y<<endl;
            fa[fa_x]=fa_y;
        }
        else{
            tot++;
            b[tot]=val;
            add(tot,fa_y);
            add(fa_y,tot);
            fa[fa_y]=tot;
            add(tot,fa_x);
            add(fa_x,tot);
            fa[fa_x]=tot;
            //cout<<tot<<" "<<fa_x<<endl;
            //cout<<tot<<" "<<fa_y<<endl;
        }
    }
    printf("%d\n",tot);
    for(int i=1;i<=tot;i++){
        printf("%d ",b[i]);
    }
    printf("\n");
    printf("%d\n",tot);
    dfs(tot,-1);
}
已标记关键词 清除标记
相关推荐
©️2020 CSDN 皮肤主题: 像素格子 设计师:CSDN官方博客 返回首页