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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

CodeForces - 618D Hamiltonian Spanning Tree(思维+贪心)

發布時間:2024/4/11 编程问答 50 豆豆
生活随笔 收集整理的這篇文章主要介紹了 CodeForces - 618D Hamiltonian Spanning Tree(思维+贪心) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

題目鏈接:點擊查看

題目大意:首先給出n個點,n*(n-1)/2條邊組成的無向圖,邊的權值為y,現在給出一棵連接n個點的樹,樹上的權值都是x,現在問如何在每個點只遍歷一次的情況下走遍n個點,并使一路上權值最小,輸出最小權值

題目分析:因為我們需要將n個點連成一條鏈,所以所需要遍歷的邊一定是n-1條邊,我們現在要做的就是分析如何讓這n-1條邊的權值和盡量小

我們可以大致分為兩種情況來分析:

  • x>=y:當樹上的權值大于圖上的權值時,我們肯定以貪心的思想盡可能的不走樹上的邊:
  • 若該圖為菊花圖,則中心點只能走樹上的邊到達其他n-1個點,故此時的答案為(n-2)*y+x
  • 若該圖不是菊花圖,則任意兩點之間肯定有非樹邊進行連接,故此時的答案為(n-1)*y
  • x<y:此時樹上的權值小于圖上的權值,所以貪心的思想肯定盡可能少的走圖上的邊,我們假設需要走ans條樹上的邊,那么答案就是ans*x+(n-1-ans)*y
  • 我們可以將第二種情況進一步分析,我們可以將n個點分為不同長度的數個區塊,每個區塊中的點都可以通過一條鏈到達,那么我們就可以用圖上的邊來連接每個區塊即可

    這樣說可能還是有點抽象,我們直接具體到某個節點來分析:

  • 若當前節點x的子節點數大于等于2,那么我們任取兩個子節點,根據貪心的思想,將這兩個子節點和節點x相連為一條鏈,分為一個單獨的區塊,那么剩下的子節點,肯定不能通過節點x到達其祖先節點了,所以只能通過圖上的邊與其他的點相連
  • 若當前節點x的子節點數小于等于1,我們可以直接將其子節點與節點x相連,并且繼續向上延伸,就不用圖上的邊輔助了
  • 根據上面兩種情況設計一下dfs求出ans,答案就出來了

    代碼:

    #include<iostream> #include<cstdlib> #include<string> #include<cstring> #include<cstdio> #include<algorithm> #include<climits> #include<cmath> #include<cctype> #include<stack> #include<queue> #include<list> #include<vector> #include<set> #include<map> #include<sstream> using namespace std;typedef long long LL;const int inf=0x3f3f3f3f;const int N=2e5+100;vector<int>node[N];int ans=0;bool dfs(int u,int f) {int son=2;//子節點數for(auto v:node[u]){if(v==f)continue;if(dfs(v,u)&&son)//若此時節點u的子節點v可以順上來一條鏈,并且當前子節點是前兩個,那么就可以將節點u和節點v用樹邊連接 //若此時節點u的子節點v已經是大于等于2的子節點了,就不能通過樹邊連接節點u和節點v了{son--;ans++;}}return son>0;//如果節點u的子節點數小于等于1,那么就可以順一條鏈上去,否則就是情況1,也就是節點u被兩個子節點所占用 }int main() { // freopen("input.txt","r",stdin); // ios::sync_with_stdio(false);int n,x,y;scanf("%d%d%d",&n,&x,&y);for(int i=1;i<n;i++){int u,v;scanf("%d%d",&u,&v);node[u].push_back(v);node[v].push_back(u);}if(x>=y){bool flag=true;for(int i=1;i<=n;i++)if(node[i].size()==n-1)//判斷菊花圖{flag=false;break;}if(flag)printf("%lld\n",1LL*(n-1)*y);elseprintf("%lld\n",1LL*(n-2)*y+x);}else{dfs(1,0);printf("%lld\n",1LL*ans*x+1LL*(n-1-ans)*y);}return 0; }

    ?

    總結

    以上是生活随笔為你收集整理的CodeForces - 618D Hamiltonian Spanning Tree(思维+贪心)的全部內容,希望文章能夠幫你解決所遇到的問題。

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