题意:
构造一棵树,现给出叶子节点的个数,以及两两叶子节点的 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);
}