日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

CF767C Garland

發布時間:2024/8/26 编程问答 40 豆豆
生活随笔 收集整理的這篇文章主要介紹了 CF767C Garland 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

一道樹形DP

\(Translate\)

有一顆\(n\)個節點的樹
\(i\)個節點權值為\(a_i\) \((n<=10^6,-100<=a_i<=100)\)
問是否能夠刪除掉兩條邊,使得該樹分成三個不為空的部分,并且每部分權值之和相等。

無解輸出\(?1\) 否則輸出要刪除邊\((u?>v)\)的v節點序號。

\(Solution\)

很明顯我們可以在\(DFS\)遍歷樹的時候記錄子樹和這個節點的權值和,我們要要將這個樹分成三部分,每部分權值和都為\(Sum/3\),所以當我們找到當前的和為\(Sum/3\)時,就可以\(cnt++\),然后記錄下這個點,千萬不要忘了將現在的求和數組清零,因為如果從這里斷開,這個節點對它的父節點將沒有貢獻,最后找完,如果\(cnt<=2\),說明分成的子樹個數\(<=2\)而不是斷邊\(<=2\),這點要注意。這時候輸出\(-1\)即可,否則說明這顆樹可以分成三部分,輸出\(ans[1],ans[2]\)即可。

剪枝

這個題剪枝十分明顯,也比較好想,我們只要在\(dp\)前判斷所有的權值和能否被\(3\)整除即可,優化十分有效。

\(Code\)

#include<iostream> #include<cstdio> #include<cmath> #include<algorithm> #define LL long long #define maxn 1000001 using namespace std; struct Edge{int nxt,to,from; }edge[maxn*2];//因為這是個樹 int num_edge,head[maxn],a[maxn],n,fa,total,sum,cnt,ans[maxn],ksum[maxn]; inline int qread(){char ch=getchar();int f=1,x=0;while(ch>'9'||ch<'0'){if(ch=='-') f=-1;ch=getchar();}while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}return x*f; } inline void addedge(int from,int to){ //加上from的原因是我們要輸出他的from edge[++num_edge].nxt=head[from];edge[num_edge].from=from;edge[num_edge].to=to;head[from]=num_edge; } int dfs(int x,int fath){ksum[x]=a[x];for(int i=head[x];i;i=edge[i].nxt){//找祖先 int y=edge[i].to;if(y!=fath){dfs(y,x);ksum[x]+=ksum[y];}}if(ksum[x]==sum){ //當滿足了之后 cnt++;ans[cnt]=x;ksum[x]=0;} } int main(){n=qread();//快讀,否則的話大數據卡死 for(int i=1;i<=n;i++){int x;x=qread();a[i]=qread();if(x!=0) {addedge(i,x);addedge(x,i);}else fa=i;total+=a[i];}if(total%3!=0) printf("-1\n");else{sum=total/3;dfs(fa,0);if(cnt>=3) printf("%d %d\n",ans[2],ans[1]);else printf("-1\n");}return 0; }

\(Addition\)

在寫這里之前還有一個問題不太理解,那就是為什么要寫\(cnt>=3\)而不能寫\(cnt==3\),不是只會分成三個塊嗎?
下面這段代碼我倒是能理解

#include<bits/stdc++.h>using namespace std;struct Edge {int to,nxt;Edge(){}Edge(int to,int nxt):to(to),nxt(nxt){} }e[1000010]; int head[1000010],cnt;void addedge(int u,int v) {e[++cnt]=Edge(v,head[u]);head[u]=cnt; }int n,m;int siz[1000010]; int ans=0; bool cut=0;void dfs(int now,int fa) {for(int i=head[now];i;i=e[i].nxt){int vs=e[i].to;if(vs==fa) continue;dfs(vs,now);siz[now]+=siz[vs];}if(siz[now]==m){if(cut) {cout<<ans<<' '<<now<<'\n';//找到第二處直接輸出exit(0);}else {ans=now;cut=1;}siz[now]=0;} }int main() {ios::sync_with_stdio(0);cin.tie(0),cout.tie(0);cin>>n;int root;for(int i=1;i<=n;i++){int tmp;cin>>tmp>>siz[i];m+=siz[i];if(tmp) addedge(tmp,i);else root=i;}if(m%3) return cout<<-1<<'\n',0;m/=3;dfs(root,0);cout<<-1<<'\n'; }

轉載于:https://www.cnblogs.com/Liuz8848/p/10876984.html

總結

以上是生活随笔為你收集整理的CF767C Garland的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。