zoukankan      html  css  js  c++  java
  • codeforces 1282 E. The Cake Is a Lie (dfs+构造)

    链接:https://codeforces.com/contest/1282/problem/E

    题意:给的是一张平面图,是一个n边形,每次可以切一刀,切出一个三角形,最终切成n-2个三角形。题目给出所切三角形的三个顶点的编号,以及三角形的编号。问你切出的三角形顺序,以及按顺序输出原始n边形顶点的所有编号,可以逆序输出也顺序输出。

    题解:有点类似拓扑排序。首先输入三角形三个点,a,b,c,统计出V[a] Xor b Xor c,同理统计V[b],V[c],这样可以保证V[i]的值只能是0 Xor 与i相连的两个点,即使三角形有共用边,多次Xor会消除公用边相连的点。根据这个性质,可以顺序输出所有点的编号。

             那么三角形顺序怎么输出呢?首先发现如果一条边是被两个三角形公用的,那么可以依据这条边把两个三角形相连,这样把三角形作为一个节点从而形成了一个图,这个图结构是一颗树,我们就随便找一个叶子节点,从叶子节点开始dfs遍历一遍,输出三角形编号即可。

    AC代码:

     1 #include<iostream>
     2 #include<vector>
     3 #include<cstring>
     4 #include<map>
     5 #include<algorithm>
     6 using namespace std;
     7 const int maxn = 1e+5;
     8 int v[maxn];
     9 vector<int> g[maxn];
    10 int visit[maxn];
    11 void dfs(int x){ //从叶子节点开始搜索,因为叶子节点必定代表着最靠外的三角形,它的度是1
    12     visit[x] = 1;
    13     for(int i = 0;i<g[x].size() ;i++){
    14         int cur = g[x][i];
    15         if(visit[cur] ==0) dfs(g[x][i]);
    16 //        dfs(g[x][i]);
    17     }
    18     cout<<x<<" ";
    19 }
    20 int main(){
    21     int t;cin>>t;
    22     while(t--){
    23         int n;
    24         cin>>n;
    25         for(int i = 0;i<=maxn;i++){
    26             v[i] = 0;//初始化V数组
    27             visit[i] = 0;//初始化访问数组
    28             g[i].clear() ;
    29         }
    30         map<pair<int,int>,vector<int> > mp;
    31         for(int i = 0;i<n-2;i++){
    32             int a,b,c;
    33             cin>>a>>b>>c;
    34             if(a>b) swap(a,b);
    35             if(b>c) swap(b,c);
    36             if(a>b) swap(a,b);
    37             v[a]^=b,v[a]^=c;//Xor操作
    38             v[b]^=a,v[b]^=c;
    39             v[c]^=a,v[c]^=b;
    40             mp[{a,b}].push_back(i+1);//添加一条边a,b,以及所共用的三角形i+1
    41             mp[{a,c}].push_back(i+1);
    42             mp[{b,c}].push_back(i+1);
    43         }
    44         int a,b;
    45         for(auto h:mp){
    46             if(h.second.size()==1){ //随便找一条边,只共用一个三角形
    47                 a = h.first.first;
    48                 b = h.first.second;
    49             //    break;
    50             }
    51         }
    52         cout<<a<<" "<<b;//输出这条边
    53         for(int i = 0;i<n-2;i++){
    54             int t = a^v[b];//开始做Xor操作。具体可以用笔模拟一下这个过程,理解更清楚
    55             cout<<" "<<t;
    56             a = b,b = t;
    57         }
    58         cout<<endl;
    59         for(auto h:mp){
    60             if(h.second.size() == 2){
    61                 int u = h.second[0],v = h.second[1];
    62                 g[u].push_back(v),g[v].push_back(u);//根据共用边以三角形为一个点建图
    63             }
    64         }
    65         dfs(1);
    66         cout<<endl;
    67     }
    68     return 0;
    69 }
  • 相关阅读:
    linux系统下安全管理
    Linux查看所有用户用什么命令
    linux下配置ip地址四种方法(图文方法)
    如何在linux系统中设置静态ip地址
    算法与cpu
    汇编 分支之跳转结构程序设计--待处理文档
    从汇编的角度理解程序(二)—— 分支和循环控制
    指令计数器--Program counter
    类型的分类
    CPU的内部架构和工作原理
  • 原文地址:https://www.cnblogs.com/AaronChang/p/12130172.html
Copyright © 2011-2022 走看看