考慮鏈上的情況,最優解肯定是兩兩相鄰的交換,如果還有多,就再多交換一次
因此樹上的也是類似,實際上就是求解乙個最小邊覆蓋問題,選擇一條邊就是交換邊兩端的點編號
可以\(o(n)\)貪心/dp求解樹上最小邊覆蓋
\[\
\]考慮理想的最優情況:對於任意一條邊,我們要求它被經過次數盡可能多
如果這條邊兩端子樹大小分別為\(a,b\),則它被經過的最多次數顯然是\(2\min\\)
考慮找到樹的重心,以它為根,此時任意一顆真子樹的大小\(\leq \frac\)
為了構造最優答案,只需要每棵子樹的集合相互錯開即可
一種簡單的構造方法是:取\(\text\)序,平移\(\frac\)即可得到解
#includeusing namespace std;
typedef long long ll;
#define pb push_back
#define rep(i,a,b) for(int i=a,i##end=b;i<=i##end;++i)
#define drep(i,a,b) for(int i=a,i##end=b;i>=i##end;--i)
template inline void cmax(t &a,t b)
if(!vis[u] && !f) vis[u]=1,swap(ans1[u],ans1[g[u][0]]),min+=2;
}int a[n],c;
int mi=1e9,rt,sz[n];
// 找重心
void dfs(int u,int f)
cmax(ma,n-sz[u]);
if(mi>ma) mi=ma,rt=u;
}// 遍歷dfs序
void dfs_get(int u,int f)
int main()
pre_dfs(1,0),dfs(1,0),dfs_get(rt,0);
rep(i,1,n) ans2[a[i]]=a[(i+n/2-1)%n+1];
printf("%lld %lld\n",min,max);
rep(i,1,n) printf("%d ",ans1[i]);
puts("");
rep(i,1,n) printf("%d ",ans2[i]);
puts("");
}
2 02 理解查詢模型
示例 select name from users where age 10 可以形象的看作是下面這樣 let arr let users users.foreach item 是指列與列之間進行運算得出的結果,叫做廣義投影 因為null 表達的意思是 空 null null false null ...
CI20 2 洗牌演算法
實現乙個方法,對一副牌 52張 進行洗牌,要求洗出的52 組合是的等概率的,即每種組合的概率為1 52 假設已經有乙個完美的隨機數生成器。思路 思路比較直觀,第一次從52張牌中隨機取一張出來,概率為1 52 第二次從剩下的51張隨機取一張出來,概率為1 51 以此類推最終的概率就是1 52 接下來是...
axp202電源管理
問題 充電電流被限制,導致充電時間過長。版本分支 android4.3 master 復現問題,檢測電流變化,發現機器在深度休眠後電流會由原來的1.2a變成0.5a。猜測 可能是由於充電電流過小導致充電時間過長。echo 30 sys class axppower axpreg cat sys cl...