noip2018 旅行 加強版

2022-05-16 00:48:11 字數 1260 閱讀 2698

\(o(n^2logn)\)很好做,直接暴力斷邊。

同樣考慮貪心,每次往最小的點走一定更優,只不過我們可以在乙個環上走一半之後回溯,使得答案更優

我們在 當前點 最近的 還有兒子沒走的祖先的 最小的兒子比當前點的兒子小時 就回溯

當然這個回溯的兒子必須在環上,且必須是當前點最大的兒子,因為如果不是最大的兒子,就必須要在其他比他更大的兒子訪問完後再回溯,這樣不滿足字典序最小

正確性是顯然的,我們要讓字典序最小,只需排在前面的最小,並且所有點必須被訪問到,所以當前點的其他兒子必須被訪問到(回溯後就無法再訪問了),且不能回溯到乙個更遠的祖先(因為更近的祖先還有兒子沒走)

實現較為複雜,細節較多

#includeusing namespace std;

#define go(i,a,b) for(int i=a;i<=b;++i)

#define com(i,a,b) for(int i=a;i>=b;--i)

#define mem(a,b) memset(a,b,sizeof(a))

#define fo(i,a) for(int i=0;ians;

bool vis[n],cir[n],flag;

void add(int u,int v);

head[u]=cnt++;

}il void read(int &x)

while(c>='0'&&c<='9')

x*=f;

}bool dfs(int u,int fa)while(x!=u);

return 1;

} s[++top]=u;

vis[u]=1;

for(int i=head[u],v;i+1;i=e[i].nxt)

--top;

vis[u]=0;

return 0;

}void dfs(int u,int last)

sort(tmp.begin(),tmp.end());

fo(i,tmp.size())

mn=inf;

if(cir[u]&&i+1!=tmp.size()) mn=tmp[i+1];

dfs(v,mn==inf?last:mn); }}

int main()

dfs(1,0);

mem(vis,0);

dfs(1,inf);

fo(i,ans.size()) printf("%d ",ans[i]);

return 0;

}

NOIp 2018 旅行 題解

題目傳送門 題目大意 現在有一棵樹或一張只有乙個環的圖 連通 要求遍歷一遍這個圖,遍歷的順序即為乙個長度為 n nn 的序列,要求字典序最小的序列。假如是一棵樹的話,顯然貪心即可,從 1 11 出發,每次往編號小的走就好了。假如只是多一條邊的話,列舉刪掉那一條邊,然後變成一棵樹來做。因為每次都要往編...

比賽 NOIP2018 旅行

發現 m 只有兩種取值,於是可做了 樹的直接貪心 圖的列舉環上的邊去掉,然後做樹的貪心,搜的時候剪一下枝吧 寫得有點亂 include define ui unsigned int define ll long long define db double define ld long double ...

NOIP2018 旅行 基環樹

小 y 是乙個愛好旅行的 oier。她來到 x 國,打算將各個城市都玩一遍。小y了解到,x國的 n nn 個城市之間有 m mm 條雙向道路。每條雙向道路連線兩個城市。不存在兩條連線同一對城市的道路,也不存在一條連線乙個城市和它本身的道路。並且,從任意乙個城市出發,通過這些道路都可以到達任意乙個其他...