洛谷P1351 聯合權值(無根樹轉化為有根樹)

2021-09-26 14:40:07 字數 1506 閱讀 9231

先將所給的圖(無根樹)轉化為有根樹,可以用一遍dfs完成。

轉化為有根樹後,對於i點,能夠產生與它聯合權值的點,要麼是它第乙個祖先(或孫子),要麼是與它深度相同的兄弟。i與它的祖先(孫子)產生的聯合權值容易計算,可以在o(1)內完成,但是與它的兄弟的權值,用樸素的演算法就需要o(n)了,例如i1,i2,i3的父節點都為k,那麼i1,i2,i3之間總的聯合權值就為:2 * ( w[i1] * w[i2] + w[i1] * w[i3] + w[i2] * w[i3] )。然而用樸素演算法做的會tle,所以得考慮優化。

我們分開來觀察一下,對於i1其聯合權值為,w[i1] * ( w[i2] + w[i3] ),i2為 w[i2] * w[i3], i3為0。現在記sum=w[i1] + w[i2] + w[i3],那麼上式會化為,w[i1] * ( sum- w[i1] ),w[i2] * ( sum- w[i1] - w[i2] ),w[i3] * ( sum - w[i1] - w[i2] - w[i3] ),因此,我們可以對於每個節點,記錄它的子節點所有權值之和,另外,對於某個父節點k,我們通過有序遍歷它的子節點,這樣就可以設定temp,記錄遍歷過程中經過的子節點權值和,如此一來,對於k的某一子節點i,其聯合權值就可以簡化為w[i] * (sum - temp)。

ps:以上各個過程均通過dfs完成。

**如下:

#include#include#include#include#include#include#include#include#pragma comment(linker,"/stack:102400000,102400000")

using namespace std;

typedef long long ll;

const int maxn=2e5+5;

const int mod=10007;

ll w[maxn],ans,sum;

int head[maxn],cnt,fa[maxn];

bool vis[maxn];

struct node

}node[maxn];

struct edge

e[maxn<<1];

void addedge(int u,int v)

void dfs(int u,int pre,int d)

inline void out(int x)

int main()

for(int i=1;i<=n;++i)

scanf("%lld",&w[i]);

fa[0]=w[0]=0;

dfs(1,0,1);

sum=0; ans=0;

for(int i=1;i<=n;++i) vis[i]=0;

dfs(1);

printf("%lld %lld\n",ans,(2*sum)%mod);

return 0;

}

洛谷P1351 聯合權值

無向連通圖g 有n 個點,n 1 條邊。點從1 到n 依次編號,編號為 i 的點的權值為w i 每條邊的長度均為1 圖上兩點 u v 的距離定義為u 點到v 點的最短距離。對於圖g 上的點對 u,v 若它們的距離為2 則它們之間會產生wu wv 的聯合權值。請問圖g 上所有可產生聯合權值的有序點對中...

P1351 聯合權值

無向連通圖g有n個點,n 1 條邊。點從1到n依次編號,編號為i的點的權值為w i 每條邊的長度均為 1。圖上兩點 u,v 的距離定義為 u 點到 v 點的最短距離。對於圖 g 上的點對 u,v 若它們的距離為 2,則它們之間會產生wv wu的聯合權值。請問圖 g上所有可產生聯合權值的有序點對中,聯...

P1351 聯合權值

然而這只是一道普及 提高的大水題 洛谷鏈結 這道題是2014年提高組day1的第二題。簡單題意就是在樹上每個點都有權值,相鄰兩點的距離為1,求距離為2的點的權值乘積的和以及最大值。基本思路就是遍歷整棵樹,然後找到距離該點距離為2的點,計算距離,更新最大值和乘積和。但這樣就很慢了。所以我們可以遍歷中間...