1. 程式人生 > >【題解】洛谷P1351 聯合權值(dfs、LCA)

【題解】洛谷P1351 聯合權值(dfs、LCA)

這道題一開始啥也沒想就用最短路寫,才40分,然後發現自己對尋找最大值取模了,改了之後60分。。然後又發現n個點,n-1條邊,其實這個圖就是一棵樹,每一個點到其餘點的最短路有且只有一條,完全可以用dfs對每個點進行擴充套件,擴充套件兩層找到點然後進行操作。。雖然看起來更簡便了,但還是60分,所以我們得想更好的方法。

為啥它讓你找距離為2的點而不是距離為3、4……的點呢?我們可以發現,對於一箇中心結點,它的所有兒子相互之間的距離都是2。這個性質很重要,我們就可以利用它,列舉每一個點為中心結點,求出它所有兒子兩兩之間的聯合權值,但不免有些繁瑣。所以我們可以把它所有兒子的權值和相加,然後平方,最後減去每一個權值的平方,就能得到以該點為中心結點情況下所有兒子之間聯合權值之和。出現加法或乘法就取模,注意減法取模可能為負數,在取模後要加上模數再取模。然後還要存下每個中心結點情況下的子節點權值最大值和最小值,相乘得到該情況下最大聯合權值,最後將所有點為中心結點的最大聯合權值取最大值就是輸出的第一個結果,第二個結果就是每一箇中心結點情況下聯合權值之和。

#include<cstdio>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#define mod 10007	
#define ll long long
using namespace std;
const int maxn=200010;
int head[maxn*2],nnext[maxn*2],to[maxn*2];
ll w[maxn];
int n,tot;
ll sum=0,ans=-1e9;
void add(int x,int y)
{
	tot++;
	nnext[tot]=head[x];
	head[x]=tot;
	to[tot]=y;
}
void dfs(int x)
{
	ll ans1=-1e9,ans2=-1e9;
	ll sum1=0;
	int p1;
	for(int i=head[x];i;i=nnext[i])
	{
		int y=to[i];
		sum1=(sum1+w[y])%mod;
		if(w[y]>ans1)
		{
			ans1=w[y];
			p1=y;
		}
	}
	sum1=sum1*sum1%mod;
	for(int i=head[x];i;i=nnext[i])
	{
		int y=to[i];
		sum1=((sum1-w[y]*w[y]%mod)%mod+mod)%mod;
		if(w[y]>ans2&&y!=p1)
		{
			ans2=w[y];
		}
	}
	sum=(sum+sum1)%mod;
//	cout<<ans1<<' '<<ans2<<' '<<sum%mod<<' '<<endl;
	ans=max(ans,ans1*ans2);
	return ;
}

int main()
{
	scanf("%d",&n);
	for(int i=1;i<=n-1;i++)
	{
		int x,y;
		scanf("%d%d",&x,&y);
		add(x,y);
		add(y,x);
	}
	for(int i=1;i<=n;i++)
	{
		scanf("%lld",&w[i]);
	}
	for(int i=1;i<=n;i++)
	{
		dfs(i);
		
	}
	printf("%lld %lld",ans,sum%mod);
	return 0;
}

相關推薦

題解P1351 聯合dfsLCA

這道題一開始啥也沒想就用最短路寫,才40分,然後發現自己對尋找最大值取模了,改了之後60分。。然後又發現n個點,n-1條邊,其實這個圖就是一棵樹,每一個點到其餘點的最短路有且只有一條,完全可以用dfs對每個點進行擴充套件,擴充套件兩層找到點然後進行操作。。雖然看起來更簡便了,

題解P1315 [NOIP2011TG] 觀光公交字首和+貪心

次元傳送門:洛谷P1315 思路 思路大概想到了 可是程式碼實現卻沒想到 所以參考題解了 D2T3的貪心果然有難度 我們考慮在每次用加速器有兩種情況 到下一個點還需要等待:以後的時間就不再影響了 到下一個點不需要等待:那麼就會影響到後面的時間直到出現情況1(或者到最後一個點) 用sum

題解P1879 [USACO06NOV] Corn Fields狀壓DP

洛谷P1879:https://www.luogu.org/problemnew/show/P1879 思路 把題目翻譯成人話 在n*m的棋盤 每個格子不是0就是1 1表示可以種 0表示不能種 相鄰的格子不能同時種 求總方案數 把每行看成一個n位的2進位制數 預處理出每行的狀態後 進行DP

題解P1896 [SCOI2005] 互不侵犯狀壓DP

洛谷P1896:https://www.luogu.org/problemnew/show/P1896 前言 這是一道狀壓DP的經典題  原來已經做過了 但是快要NOIP 複習一波 關於一些位運算的知識點參考: https://blog.csdn.net/fox641941

P1351 聯合NOIp2014

技巧題 題目傳送門 題目意思很簡單,求兩個距離為2的點的點權。可以轉化為求一個點其中兩條出邊的點權。 剛開始寫DFS,然後華麗麗地T掉了。。。以為哪裡寫掛了,算了一下發現是O(n2)O(n2)的。。。於是重新想演算法 後來發現一個公式:2∗(a[1]∗a

——P1351 聯合

problem org cto 輸入 最大的 -m http color 說明 https://www.luogu.org/problem/show?pid=1351 題目描述 無向連通圖G 有n 個點,n - 1 條邊。點從1 到n 依次編號,編號為 i 的點的權值為

P1351 聯合(樹形dp)

+= math getc esp std () num del const 題意 題目鏈接 Sol 一道很簡單的樹形dp,然而被我寫的這麽長 分別記錄下距離為\(1/2\)的點數,權值和,最大值。以及相鄰兒子之間的貢獻。 樹形dp一波。。 #include<bits/

題解P1169 [ZJOI2007] 棋盤製作座標DP+懸線法

次元傳送門:洛谷P1169 思路 浙江省選果然不一般 用到一個從來沒有聽過的演算法 懸線法: 所謂懸線法 就是用一條線(長度任意)在矩陣中判斷這條線能到達的最左邊和最右邊及這條線的長度 即可得到這個矩陣的最大值 那麼我們定義3個數組 l[i][j]表示(i,j)能到達最左邊的座標 r[i][j]

題解P1092[NOIP2004]蟲食算 dfs

題目連結 參考了大佬題解中的剪枝操作 #include<cstdio> #include<map> #include<cstdlib> using namespace std; int n,vis[27]; char

題解1600天天愛跑步NOIP2016

在這裡給大家提供一種非常簡單的方法。 我們先來轉化一下題面:題目要求我們求每一個點在某個時間能看到的人數,那我們也可以分別計算每一個人對於他跑步的那條路徑上的貢獻。 那麼我們可以發現一個顯而易見的事情:這條路經一定由一段上行和一段下行組成。而且有且只有這兩條路徑

題解P1975排序

space getchar() class std -- names char 圖書管理員 wap 分塊,註意重復的值之間的處理。跟普通分塊的操作一樣的啦,具體可以參見‘不勤勞的圖書管理員’。 #include <bits/stdc++.h> using na

題解P2418 yyy loves OI IV

轉移 || 暴力 兩種 clu OS AD spa IT 感覺很是妙啊……這題數次誤入歧途...最開始想的二維dp,單調隊列優化;無果,卒。於是沒忍住看了下標簽:暴力枚舉?搜索?於是開始想記憶化搜索。以為會有什麽很強的剪枝之類的;30分,卒。最後終於回到正道上:50 000

題解6月月賽 —— 「數學」約數個數和

分解 pri clas left pac 這樣的 DC 兩個 探測   看德國戰墨西哥去了結果發現比賽只剩下30分鐘……當然之後又思考這題挺久也還是不會做。看了一下題解,覺得這個做法挺厲害的,在這裏記錄一下:   原式實際上就是:(\(K +=

題解P1941 [NOIP2014TG] 飛揚的小鳥揹包DP

次元傳送門:洛谷P1941 思路 從題意可知 在每個單位時間內 可以無限地向上飛 但是隻能向下掉一次 所以我們可以考慮運用揹包解決這道題 上升時 用完全揹包 下降時 用01揹包 設f[x][y]為在座標(x,y)時的最小點選螢幕次數 當飛到天花板時和撞到柱子時特判 一開始設ans為極大值 如

題解P1373 小a和uim之大逃離座標DP

次元傳送門:洛谷P1373 思路 設f[i][j][t][1/0]表示走到(i,j)時 小a減去uim的差值為t 當前是小a取(0) uim取(1) 那麼轉移就很明顯了 f[i][j][t][0]=(f[i][j][t][0]+f[i-1][j][(t-map[i][j]+k)%k][1])%1

題解P1273 有線電視網樹上分組揹包

次元傳送門:洛谷P1273 思路 一開始想的是普通樹形DP 但是好像實現不大好 觀摩了一下題解 是樹上分組揹包 設f[i][j]為以i為根的子樹中取j個客戶得到的總價值 我們可以以i為根有j組 在每一組中分別又取1個,2個,3個......n個客戶 化為揹包思想即 j為一共有j組 揹包容量為每

題解 1120 小木棍 [資料加強版]

原題 剪枝好題,可以有以下9個剪枝(基本上都是可行性剪枝,還有一些搜尋順序的剪枝),這是一道除了生日蛋糕以外的剪枝好題當然不會告訴你Biscuit46花了1h做這道題目 #include<stdio.h> #include<stdlib.h> #include<strin

題解P2577 [ZJOI2005] 午餐DP+貪心

次元傳送門:洛谷P2577  思路 首先貪心是必須的 我們能感性地理解出吃飯慢的必須先吃飯(結合一下生活) 因此我們可以先按吃飯時間從大到小排序 然後就能自然地想到用f[i][j][k]表示前i個人在第一個視窗排隊用了j時間 在第二個視窗排隊用了k時間 然後就自然地炸空間了 所以我們要

題解P1070 道路遊戲線性DP

次元傳送門:洛谷P1070 思路 一開始以為要用什麼玄學優化 沒想到O3就可以過了 我們只需要設f[i]為到時間i時的最多金幣 需要倒著推回去 即當前值可以從某個點來 那麼狀態轉移方程為: f[i]=max(f[i],f[i-k]+val-cost[now]); now表示從now這個

題解P3959 [NOIP2017TG] 寶藏狀壓DP+DFS

洛谷P3959:https://www.luogu.org/problemnew/show/P3959 前言 NOIP2017時還很弱(現在也很弱 看出來是DP 但是並不會狀壓DP 現在看來思路並不複雜 只是存狀態有點難想到 思路 因為n最大為12 所以可以想到是狀壓