1. 程式人生 > 其它 >Codeforces Round #793 D. Circular Spanning Tree(構造)

Codeforces Round #793 D. Circular Spanning Tree(構造)

思路:首先討論點的度數,整個點的度數應該都是偶數的(每條邊貢獻兩度),那就意味這奇數點的個數是偶數

所以奇數點的個數是奇數的直接輸出NO

接下來則討論如何構造不存在交叉邊的圖

對於這樣一個圖

 要構造所有邊都儘量不相鄰的方法是

 即一個類似樹的結構,我們很自然會想到構建一個樹

為了保證偶數點的的度為偶數,我們可以將它們串聯成一條鏈,鏈尾是奇數點(即葉子節點)

之後則是隨機找一個偶數點作為樹的頂點

鏈條個數取決於奇數點個數,所以保證頂點度數不會被改變

AC程式碼:

#pragma GCC optimize(2)
#pragma GCC optimize(1)
#include<bits/stdc++.h>
typedef 
long long ll; typedef unsigned long long ull; const ull base=131; #define MAX 1009 #define PI 3.141592653589793 using namespace std; inline void solve(){ int len; string op; cin>>len>>op;op=" "+op; int c=0; for(int i=1;i<=len;i++) if(op[i]=='1')c++; if(c%2||c<2
){ cout<<"No"<<"\n";return; } cout<<"Yes\n"; vector<pair<int,int>> edge;//存邊 vector<int> lank[len+3]; int beg=1; int num=1,time=0; for(;beg<=len;beg++) if(op[beg]=='1')break;//記錄第一個1的位置 while(1){ while(1){ lank[num].push_back(beg);
if(beg<len) beg++; else beg=1; time++; if(op[beg]=='1'||time==len) break; } reverse(lank[num].begin(), lank[num].end()); if(time==len) { break; } num++; } int txt=lank[num][0]; for(int i=1;i<num;i++){ edge.push_back({lank[i][0],txt}); } for(int i=1;i<=num;i++){ int si=lank[i].size(); for(int j=0;j<si-1;j++){ edge.push_back({lank[i][j],lank[i][j+1]}); } } int all=edge.size(); for(int i=0;i<all;i++) cout<<edge[i].first<<' '<<edge[i].second<<"\n"; } int main() { std::ios::sync_with_stdio(false); std::cin.tie(0); int sum;cin>>sum; while(sum--){ solve(); } }