zoukankan      html  css  js  c++  java
  • [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;
    }
    
  • 相关阅读:
    springboot 整合 memcached l
    文件处理工具类 l
    执行脚本工具类 l
    LRU l
    归并排序 l
    Redis 数据类型 l
    git 常用操作命令 唏嘘
    postmanPOST请求 status 415错误 唏嘘
    MySQL 启动和关闭MySQL服务 唏嘘
    OO和OP
  • 原文地址:https://www.cnblogs.com/AEMShana/p/12356572.html
Copyright © 2011-2022 走看看