先找到一条多边形的边,然后循环一圈输出多边形上的点。把每个三角形看作一个结点,以两个三角形之间公用边为边建立一张图,DFS输出叶子结点,则得到先切后切的顺序。
1 #define HAVE_STRUCT_TIMESPEC 2 #include<bits/stdc++.h> 3 using namespace std; 4 vector<int>v[100007]; 5 bool vis[100007]; 6 void dfs(int x){ 7 vis[x]=1; 8 for(auto it:v[x]) 9 if(!vis[it]) 10 dfs(it); 11 cout<<x<<" ";//把三角形看作是一个结点,输出叶子结点即为外圈的三角形,它们是可以被先切的,内圈的三角形后输出为后切的 12 } 13 int main(){ 14 ios::sync_with_stdio(false); 15 cin.tie(NULL); 16 cout.tie(NULL); 17 int t; 18 cin>>t; 19 while(t--){ 20 int n; 21 cin>>n; 22 for(int i=1;i<=n;++i){ 23 vis[i]=0; 24 v[i].clear(); 25 } 26 int adj[n+1]={0};//每次和三角形中另外两个点异或,最终得到的是它相邻的两个点的异或和 27 map<pair<int,int>,vector<int> >mp; 28 for(int i=1;i<=n-2;++i){ 29 int a,b,c; 30 cin>>a>>b>>c; 31 adj[a]^=b; 32 adj[a]^=c; 33 adj[b]^=a; 34 adj[b]^=c; 35 adj[c]^=a; 36 adj[c]^=b; 37 if(a>b) 38 swap(a,b); 39 if(b>c) 40 swap(b,c); 41 if(a>b) 42 swap(a,b);//为了使abc有序,否则可能因为输入顺序的原因把同对的两个点顺序搞反 43 mp[{a,b}].push_back(i); 44 mp[{b,c}].push_back(i); 45 mp[{a,c}].push_back(i); 46 } 47 int x=0,y=0; 48 for(auto it:mp){ 49 if(it.second.size()==1){//只属于一个三角形的边一定是原本多边形的一条边 50 x=it.first.first;//x和y一定相邻 51 y=it.first.second; 52 break; 53 } 54 } 55 cout<<x<<" "<<y<<" "; 56 for(int i=1;i<=n-2;++i){//已知x是y的一个相邻点,又知道y的两个相邻点的异或和adj[y],可以得到另一个相邻点x^adj[y] 57 adj[y]^=x; 58 cout<<adj[y]<<" "; 59 x=y; 60 y=adj[y]; 61 } 62 cout<<" "; 63 //x=0,y=0; 64 for(auto it:mp){ 65 if(it.second.size()==2){//某条边被两个三角形所共用,就将这两个三角形之间连一条边 66 x=it.second[0]; 67 y=it.second[1]; 68 v[x].push_back(y); 69 v[y].push_back(x); 70 } 71 } 72 dfs(1); 73 cout<<" "; 74 } 75 return 0; 76 }