[构造] Codeforces 1278E Tests for problem D

题目大意

给定一棵\(N(N\leq 5 \times 10^5)\)个点的树,每个点代表着一个线段,所有线段都不存在公共端点,且端点在\([1,2\times N]\)范围内。只有当两条线段相交但不内含时,这两条线段代表的点才会相连。要求求出这\(N\)个点所代表的线段的任意一种情况。

题解

我们去维护一个链表,开始时指定1号结点为根结点,并把1号结点的所代表的线段的两个端点插入链表。然后从1号结点进行DFS。每遍历到一个结点,就把它所代表的线段的左端点插入它父亲所代表的线段的右端点的左边,再把它所代表的线段的右端点插入它父亲所代表的线段的右端点的右边。最后遍历整个链表,给每个端点分配一个下标即可。时间复杂度\(O(N)\)

Code

#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
using namespace std;

#define RG register int
#define LL long long

template<typename elemType>
inline void Read(elemType &T){
    elemType X=0,w=0; char ch=0;
    while(!isdigit(ch)) {w|=ch=='-';ch=getchar();}
    while(isdigit(ch)) X=(X<<3)+(X<<1)+(ch^48),ch=getchar();
    T=(w?-X:X);
}

struct Node{int L,R;};
Node LinkList[1000010];
Node Ans[500010];
struct edge{int Next,to;};
edge G[1000010];
int head[500010];
int N,cnt=2,Index=0;

inline void Add_Edge(int u,int v){
    G[cnt].to=v;
    G[cnt].Next=head[u];
    head[u]=cnt++;
}

inline void Maintain(int u,int fa){
    int B=LinkList[fa<<1|1].L;
    LinkList[B].R=u<<1;
    LinkList[u<<1].L=B;
    LinkList[fa<<1|1].L=u<<1;
    LinkList[u<<1].R=fa<<1|1;
    B=LinkList[fa<<1|1].R;
    LinkList[B].L=u<<1|1;
    LinkList[u<<1|1].R=B;
    LinkList[fa<<1|1].R=u<<1|1;
    LinkList[u<<1|1].L=fa<<1|1;
    return;
}

void DFS(int u,int fa){
    if(fa!=0) Maintain(u,fa);
    for(int i=head[u];i;i=G[i].Next){
        int v=G[i].to;
        if(v==fa) continue;
        DFS(v,u);
    }
    return;
}

void Solve(int u){
    while(LinkList[u].R!=0){
        ++Index;
        if(u&1) Ans[u>>1].R=Index;
        else Ans[u>>1].L=Index;
        u=LinkList[u].R;
    }
    ++Index;
    if(u&1) Ans[u>>1].R=Index;
    else Ans[u>>1].L=Index;
    return;
}

int main(){
    Read(N);
    for(RG i=1;i<=N-1;++i){
        int u,v;
        Read(u);Read(v);
        Add_Edge(u,v);
        Add_Edge(v,u);
    }
    LinkList[1<<1].R=1<<1|1;
    LinkList[1<<1|1].L=1<<1;
    DFS(1,0);
    int St=0;
    for(RG i=2;i<=(N<<1|1);++i)
        if(LinkList[i].L==0){St=i;break;}
    Solve(St);
    for(RG i=1;i<=N;++i)
        printf("%d %d\n",Ans[i].L,Ans[i].R);

    return 0;
}

猜你喜欢

转载自www.cnblogs.com/AEMShana/p/12386160.html