wc2018 t1 簡化版 by oblack.
有兩棵有 n 個節點的樹,分別為 a,b,樹上每條邊都有乙個權值 v_i
令 disa(x,y) 和 disb(x,y) 分別表示 x 節點與 y 節點在樹 a,b 上的距離
請你找出乙個點對 (x,y) 使得 disa(x,y)+disb(x,y) 取得最大值,注意 x!=y
輸入格式
第一行,乙個整數 n
接下來 n-1 行,每行三個整數 x_i,y_i,v_i ,表示 a 上的一條邊
接下來 n-1 行,每行三個整數 x_i,y_i,v_i ,表示 b 上的一條邊
輸出格式
輸出乙個整數 ans ,表示最大值
樣例輸入
54 5 6
4 1 2
5 2 1
4 3 0
4 1 9
4 2 0
1 5 0
5 3 7
樣例輸出
23提示
對於 30% 的資料, n<=2000,v_i<=10^6
對於所有資料, n<=10^5, v_i<=10^12
本題為 wc2018 t1 (nkoj 5004) 簡化版我們將dis1(x,y)+dis2(x,y)變一下形 --> dep1[x] + dep1[y] - 2*dep1[lca1(x,y)] + dep2[x] + dep2[y] - 2*dep2[lca2(x,y)]
我們發現對於任何x,他的dep1[x]和dep2[x]在式子中總是成對出現的。那麼我們將他們合併在一起考慮-->方法是將第二棵樹中的x,每個對應在其下連一條dep1[x]的邊,並設定新節點為x'。同時我們在第一棵樹中列舉lca,那麼問題就變成了--->對於第一棵樹的lca,對於他的分別兩個子樹合併的時候的兩個點集,分別對應在第二棵樹中的兩個離散的點集,在其中找一條最長的路徑。也就是比如對於x的son1對應一些點集,son2對應一些點集,(因為在這兩個點集中各選乙個保證他們在第一棵樹樹上的lca一定為x)然後兩個中各自挑選乙個的最長路徑。
其實對於這樣兩個離散點集中,分別各自對應著兩個直徑。容易證明。對於兩個離散點集,他們之間的最長路徑的端點一定是分別在他們的直徑4個點上。同時,也可以證明,對於兩個離散點集他們合併之後的那個點集的直徑的端點,也一定是兩個離散點集的四個端點之二。
這樣我們只需要變換一下第二顆樹,然後在第一棵樹上dfs合併子樹,在第二顆樹上查詢最長路徑更新答案(lca次數比較多,考慮o(1)lca),就可以了。。
/*在第一棵樹上列舉lca,由於式子
disa(x,y) + disb(x,y) == dep1x + dep1y -2*lca1 + dep2x + dep2y - 2*lca2
可以在第二棵樹上外掛程式乙個節點,那麼就是對於第二棵樹上的乙個點集內的求點集了
然後直接直徑合併就可以了
*/#include#include#include#include#include#define pr pair#define fi first
#define se second
using namespace std;
typedef long long ll;
const int maxn = 1000005;
const int maxm = 2000005;
ll len1[maxm];
int la1[maxn],nt1[maxm],en1[maxm],owo1;
void addedge1(int a,int b,ll c)
ll len2[maxm];
int la2[maxn],nt2[maxm],en2[maxm],owo2;
void addedge2(int a,int b,ll c)
ll dep1[maxn],dep2[maxn];
int n;
int st[23][maxn*2],lac[maxn],oula;
char buf[1<<20],*p1,*p2;
#define gc (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<20,stdin),p1==p2)?0:*p1++)
//#define gc getchar()
inline ll r()
void dfs1(int x,int ba)
}int logg[maxn*2];
int s;
void dfs2(int x,int ba)
lac[x] = oula;
}ll ans = -1e18;
int getlca(int x,int y)
tmp = getcd(a.fi,b.fi);
if(tmp>ccd)
tmp = getcd(a.fi,b.se);
if(tmp>ccd)
tmp = getcd(a.se,b.fi);
if(tmp>ccd)
tmp = getcd(a.se,b.se);
if(tmp>ccd)
return now;
}pr dfs3(int x,int ba)
return zj;
}main()
}dfs3(1,0);
printf("%lld",ans);
}
兩棵樹的命運
農夫在地里種下了兩粒種子,很快它們變成了兩棵同樣大小的樹苗。第一棵樹開始就決心長成乙個參天大樹,所以它拼命地從地下吸收養料,儲備起來,滋潤每一枝樹幹,盤算著怎樣向上生長,完善自身。由於這個原因,在最初的幾年,它並沒有結果實,這讓農夫很惱火。相反另一棵樹,也拼命地從地下吸取養料,打算早點開花結果,它做...
判斷兩棵樹是否相等
思路 兩棵樹相等當且僅當roota data rootb data,且a和b的左右子樹相等或左右子樹互換相等 用遞迴的方式進行求解 1 if 兩棵樹都為空 返回true 2 if 兩棵樹中一棵為空,另一棵不為空 返回false 3 if 資料相等 else if 第一棵樹的左子樹與第二棵樹的右子樹相...
WPF的兩棵樹與繫結
原文 wpf的兩棵樹與繫結 public class visualpanel frameworkelement public visualpanel protected override int visualchildrencount protected override visual getvis...