[DFS][拓扑排序] Codeforces 1282E The Cake Is a Lie

题目大意


给你一个凸(N)边形,每个顶点都有一个编号,但顶点编号的顺序未知。给你该凸(N)边形拆分成的(N-2)个三角形的顶点的编号,让你求该凸多边形顶点编号的顺序,和依次切出这(N-2)个三角形的顺序。(3 leq N leq 10^5)

题解

容易发现,在多边形内部的边均被两个三角形使用,在多边形轮廓上的边只被一个三角形使用,那么哈希一下,将只使用过一次的边的两个端点连线,形成一个环,DFS一下即得出多边形顶点编号的顺序。

对于两个三角形,如果它们有一条公共边,则将这两个三角形的编号连边,容易发现,这形成了一棵树。那么就类似于拓扑排序的做法,不断去删度数小于等于1的点,然后去更新与它相邻的点的度数,如此循环,即得到切下三角形的顺序。

Code

#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <vector>
#include <queue>
#include <map>
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 triangle{int a,b,c;};
triangle Data[500010];
map<pair<int,int>,pair<int,int> > Hash;
struct edge{int Next,to;};
edge G[2000010],G2[2000010];
int head[500010],head2[500010],Degree[500010];
bool vis[500010];
vector<int> AnsA,AnsB;
int T,N,cnt=2,cnt2=2;

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

inline void Add_Edge2(int u,int v){
    G2[cnt2].to=v;
    G2[cnt2].Next=head2[u];
    head2[u]=cnt2++;
}

inline void Insert(int i){
    auto A=make_pair(min(Data[i].a,Data[i].b),max(Data[i].a,Data[i].b));
    auto B=make_pair(min(Data[i].b,Data[i].c),max(Data[i].b,Data[i].c));
    auto C=make_pair(min(Data[i].a,Data[i].c),max(Data[i].a,Data[i].c));
    auto HA=Hash[A],HB=Hash[B],HC=Hash[C];
    if(!HA.first) HA.first=i;
    else HA.second=i;
    if(!HB.first) HB.first=i;
    else HB.second=i;
    if(!HC.first) HC.first=i;
    else HC.second=i;
    Hash[A]=HA;Hash[B]=HB;Hash[C]=HC;
    return;
}

inline void Init(){
    Hash.clear();
    cnt=cnt2=2;
    fill(head,head+N+5,0);
    fill(head2,head2+N+5,0);
    fill(vis+1,vis+N+1,0);
    fill(Degree,Degree+N+5,0);
    AnsA.clear();AnsB.clear();
    return;
}

void DFSA(int u){
    vis[u]=true;
    AnsA.push_back(u);
    for(int i=head2[u];i;i=G2[i].Next){
        int v=G2[i].to;
        if(vis[v]) continue;
        DFSA(v);
    }
    return;
}

queue<int> Q;

void TopSort(){
    while(!Q.empty()) Q.pop();
    fill(vis,vis+N+5,0);
    for(RG i=1;i<=N-2;++i)
        if(Degree[i]<=1) {Q.push(i);vis[i]=true;}
    while(!Q.empty()){
        int u=Q.front();Q.pop();
        AnsB.push_back(u);
        for(int i=head[u];i;i=G[i].Next){
            int v=G[i].to;
            if(vis[v]) continue;
            --Degree[v];
            if(Degree[v]<=1){vis[v]=true;Q.push(v);}
        }
    }
    return;
}

int main(){
    Read(T);
    while(T--){
        Read(N);
        Init();
        for(RG i=1;i<=N-2;++i){
            Read(Data[i].a);
            Read(Data[i].b);
            Read(Data[i].c);
            Insert(i);
        }
        for(auto it:Hash){
            if(!it.second.second){
                Add_Edge2(it.first.first,it.first.second);
                Add_Edge2(it.first.second,it.first.first);
            }
            else{
                Add_Edge(it.second.first,it.second.second);
                Add_Edge(it.second.second,it.second.first);
                ++Degree[it.second.first];
                ++Degree[it.second.second];
            }
        }
        DFSA(1);
        TopSort();
        for(RG i=0;i<(int)AnsA.size();++i){
            printf("%d",AnsA[i]);
            if(i<(int)AnsA.size()-1) printf(" ");
        }
        printf("
");
        for(RG i=0;i<(int)AnsB.size();++i){
            printf("%d",AnsB[i]);
            if(i<(int)AnsB.size()-1) printf(" ");
        }
        printf("
");
    }
    
    return 0;
}
原文地址:https://www.cnblogs.com/AEMShana/p/12356572.html