那麼,我們用類似提直徑的方法把這條路徑給拎出來
就會形成這樣的一棵樹。
那麼,對於一條邊,若其被改成蟲洞,最長路徑會有如下三種情況:
難道我們不用考慮經過該邊的路徑嗎??
當然不用。
我們已經是在最長路徑上改造邊了,而最長路徑是長於任何一條路徑的(廢話),那麼經過該邊的任何路徑在此邊被改造後依然短於最長路徑,故不用考慮。
至於求兩端的最長路徑,我們可以字首和字尾分別維護一下。
我們可以在每個點開個vector,對於一條路徑,我們把另一端點以及路徑的編號加到vector中。
然後,再開個vis陣列,表示這個點是否被訪問過。
在遍歷時,我們訪問所有以這一點為一端點的路徑標號\(id\)和另一端點\(y\),若另\(vis[y]=true\),就拿\(id\)的長度去更新即可。(口胡不清,這最好手動模擬一下)
額,樹剖我是當常數看的。。。
實在不行你可以tarjan離線預處理啊
**(巨醜無比):
#include#define reg register int
#define maxn 300010
using namespace std;
int n,m,head[maxn],dis[maxn],tot,maxx,bh,pre[maxn],sumfr[maxn],sumla[maxn],num[maxn],lian[maxn],ans=2e9+7;
bool mark[maxn],vis[maxn];
struct node p[maxn];
struct edge g[maxn*2];
struct que ;
vectorq[maxn];
struct s__
} shupou;
void rd(int &res)
void add(int st,int ed,int v) ;
head[st]=tot;
}void dfs(int x,int fa,int &bb)
}void dfsla(int x,int fa,int zu) );
q[p[i].ed].push_back(que );
} int st=p[bh].st,ed=p[bh].ed,lca=p[bh].lca;
while(st!=lca)mark[st]=true,st=pre[st];
while(ed!=lca)mark[ed]=true,ed=pre[ed];
mark[lca]=true;
int bb=1;
dfs(p[bh].st,0,bb);
dfsfr(p[bh].st,0,num[p[bh].st]);
memset(vis,false,sizeof(vis));
dfsla(p[bh].ed,0,num[p[bh].ed]);
for(int i=1;i<=bb;i++)
cout<
return 0;
}
noip2015 運輸計畫
公元 2044 年,人類進入了宇宙紀元。l 國有 n 個星球,還有 n 1 條雙向航道,每條航道建立在兩個星球之間,這 n 1 條航道連通了 l 國的所有星球。小 p 掌管一家物流公司,該公司有很多個運輸計畫,每個運輸計畫形如 有一艘物流飛船需要從 ui 號星球沿最快的宇航路徑飛行到 vi 號星球去...
NOIP2015 運輸計畫
題目鏈結 codevs 4632 題目大意 在一棵 n 節點樹上,有 m個運輸計畫 從ai 到 bi n,m 300000 問 把哪一條樹邊的權值變為0,可以使所有運輸計畫的最大距離最小,輸出這個最大距離的最小值。分析 0.首先要會lca和樹上差分。1.顯然,這道題要求樹上兩點之間的距離,所以要寫l...
noip 2015 運輸計畫
去題面的傳送門 題目的意思是 求將一棵樹上的任意一條邊權賦值為0時,所有航線的最長長度的最小值 想到二分答案 如何驗證?既然我們二分的答案是最長路線,也就是說,在將一條邊權賦值為0之後,所有的路線長度應該都小於等於mid。但是只能刪掉一條邊,所以這條邊是所有刪邊之前長度小於mid的路線的交邊。問題轉...