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 }

猜你喜欢

转载自www.cnblogs.com/AaronChang/p/12130172.html
今日推荐