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

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

【HDU - 5886】Tower Defence(树的直径,思维,dp)

發(fā)布時(shí)間:2023/12/10 编程问答 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【HDU - 5886】Tower Defence(树的直径,思维,dp) 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

題干:

There was a civil war between two factions in Skyrim, a province of the Empire on the continent of Tamriel. The Stormcloaks, led by Ulfric Stormcloak, are made up of Skyrim's native Nord race. Their goal is an independent Skyrim free from Imperial interference. The Imperial Legion, led by General Tullius, is the military of the Empire that opposes the Stormcloaks and seeks to reunite and pacify the province.?

The current target of General Tullius is to defend Whiterun City. Near by this city there are?NN?towers under the Empire's control. There are?N?1N?1?roads link these tower, so solders can move from any tower to another one through these roads.?

In military affairs, tactical depth means the longest path between two towers of all. Larger the tactical depth is, more stable these towers are.?

According to the message sent by spies, General Tullius believe that Stormcloaks is planning to attack one of these roads, and his towers would be divided into two parts. However, Tullius does not know which one, so he supposes the possibility that Stormcloaks attack these roads are the same. Now, General Tullius ask for your help, to calculate the expectation of tactical depth after this attack.?

To avoid the issue of precision, you need to calculate?expectationoftacticaldepth×(N?1)expectationoftacticaldepth×(N?1).

Input

The first line of input contains an integer?tt, the number of test cases.?tt?test cases follow.?
For each test case, in the first line there is an integer?N(N≤100000)N(N≤100000).?
The?ii-th line of the next?N?1N?1?lines describes the?ii-th edge. Three integers?u,v,w?(0≤w≤1000)u,v,w?(0≤w≤1000)?describe an edge between?uu?and?vv?of length?ww.

Output

For each test cases, output?expectationoftacticaldepth×(N?1)expectationoftacticaldepth×(N?1).

Sample Input

2 3 2 1 2 3 2 5 5 2 1 7 3 1 7 4 2 5 5 2 6

Sample Output

7 63

題目大意:

給出一棵樹,邊上有權(quán)值,現(xiàn)在毀掉任意一條邊,分成兩部分,求這兩部分中最遠(yuǎn)的兩點(diǎn)距離期望,答案*(n-1)

一句話題意:

N個(gè)點(diǎn)的一棵帶權(quán)樹。切掉某條邊的價(jià)值為切后兩樹直徑中的最大值。求各個(gè)邊切掉后的價(jià)值和(共N-1項(xiàng))。

解題報(bào)告:

說白了就是求最遠(yuǎn)距離加成和?
對(duì)于一棵樹來說,兩點(diǎn)最遠(yuǎn)的距離,考慮兩點(diǎn):?
1.最長鏈沒有被拆開,那么答案就是最長鏈;?
2.最長鏈被拆開了,那么答案一定在最長鏈的端點(diǎn)到某個(gè)葉子結(jié)點(diǎn)上;?
第一點(diǎn)很顯然,關(guān)于第二點(diǎn)的證明很簡(jiǎn)單,假設(shè)最長路不是最長鏈的端點(diǎn)到某個(gè)葉子結(jié)點(diǎn),那么另一條更長的路徑會(huì)取代他成為樹的直徑,與已知矛盾。

有了這個(gè)結(jié)論,這個(gè)題就好做了,首先預(yù)處理出最長鏈,數(shù)組存下來,然后對(duì)于每個(gè)最長鏈上的結(jié)點(diǎn)預(yù)處理出它的權(quán)值最大的葉子結(jié)點(diǎn)(不在最長鏈上),注意這里的處理看似是n^2的,但是因?yàn)槭且豢脴?#xff0c;所以其實(shí)每個(gè)點(diǎn)只會(huì)被掃到一遍所以是線性的。剩下的就是處理最長鏈左邊和右邊的拆開后的最大值了,左右掃一遍,兩個(gè)數(shù)組LR存下來,最后On掃一遍最長鏈,取LR中最大值得到答案。?

剛開始想在bfs的過程中就處理處nxt數(shù)組和nxtw數(shù)組,后來發(fā)現(xiàn)不行,因?yàn)槟悴荒鼙WCdis[v]>ans的時(shí)候更新的一定是最終選擇的路徑,所以還是需要從起點(diǎn)到終點(diǎn)dfs一次,在回溯的時(shí)候這條路徑一定是我們選擇的。

AC代碼:

#include<cstdio> #include<iostream> #include<algorithm> #include<queue> #include<map> #include<vector> #include<set> #include<string> #include<cmath> #include<cstring> #define F first #define S second #define ll long long #define pb push_back #define pm make_pair using namespace std; typedef pair<int,int> PII; const int MAX = 2e5 + 5; struct Edge {int u,v;ll w;int ne; } e[MAX]; int head[MAX],tot,n;//記錄邊數(shù) int path[MAX],nxt[MAX],top;//top記錄最長鏈上的頂點(diǎn)數(shù) ll dis[MAX],nxtw[MAX],sum[MAX],val[MAX],L[MAX],R[MAX]; int flag[MAX]; void add(int u,int v,ll w) {e[++tot].u = u;e[tot].v = v;e[tot].w = w;e[tot].ne = head[u];head[u] = tot; } int bfs(int st,ll& ans) {queue<int> q;int retp = st;ans = 0;//注意初始化 for(int i = 1; i<=n; i++) dis[i] = -1,nxt[i]=-1;q.push(st);dis[st] = 0; while(!q.empty()) {int cur = q.front();q.pop();for(int i = head[cur]; ~i; i = e[i].ne) {int v = e[i].v;if(dis[v] != -1) continue;q.push(v);dis[v] = dis[cur] + e[i].w;if(dis[v] >= ans) {ans = dis[v];retp = v;}}}return retp; } int st,ed; bool ok; void dfs(int cur,int fa) {if(cur == ed) {ok = 1;return;}for(int i = head[cur]; ~i; i = e[i].ne) {int v = e[i].v;if(v == fa) continue;dfs(v,cur);if(ok == 1) {nxt[cur] = v;nxtw[cur] = e[i].w;return;}} } ll dfs2(int cur,int fa) {ll res = 0;for(int i = head[cur]; ~i; i = e[i].ne) {int v = e[i].v;if(flag[v] == 1 || v == fa) continue;res = max(res,dfs2(v,cur) + e[i].w);}return res; } int main() {int t;cin>>t;while(t--) {scanf("%d",&n);//inittot=top=0;ok=0;for(int i = 1; i<=n; i++) head[i] = -1,sum[i] = 0,val[i]=L[i]=R[i]=0,flag[i] = 0;for(int a,b,i = 1; i<=n-1; i++) {ll c;scanf("%d%d%lld",&a,&b,&c);add(a,b,c);add(b,a,c);}ll maxx,ans=0;st = bfs(1,maxx); ed = bfs(st,maxx);dfs(st,-1);for(int i = st; i!=-1; i = nxt[i]) {flag[i] = 1;path[++top] = i;}ans = maxx * (n-top);for(int i = 1; i<top; i++) {//枚舉他和他兒子的那條邊 sum[i+1] = sum[i] + nxtw[path[i]];//照這么來看的話還是遞歸的寫法會(huì)好一些,因?yàn)檎镁褪莾鹤庸?jié)點(diǎn)代表兒子到父親的那條邊 }for(int i = 1; i<=top; i++) {//搜索中間點(diǎn) (st和ed也可以搜,只不過搜出來結(jié)果肯定是0)val[i] = dfs2(path[i],-1);}for(int i = 1; i<=top; i++) {//枚舉割最長鏈上的每一條邊 L[i] = max(val[i] + sum[i],L[i-1]);}for(int i = top; i>=1; i--) {R[i] = max(R[i+1],val[i] + (sum[top]-sum[i]));}for(int i = 1; i<top; i++) {ans += max(L[i],R[i+1]);}printf("%lld\n",ans);}return 0 ; }

?

總結(jié)

以上是生活随笔為你收集整理的【HDU - 5886】Tower Defence(树的直径,思维,dp)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。