小g 同學總是在樹上走路。小s 看不下去了,決定阻止小g 同學。
有一棵 n 個點的樹,樹上有 m 條路徑,每條路徑為 x[i]到y[i] 的樹上最短路徑(不經過相同的邊),小 s 想要摧毀樹上的 k 個點, 使得每一條路徑上都有至少乙個點被摧毀。
你只需要求出最小的k,而不用輸出摧毀了哪些點。
資料點編號
n<=
m<=115
15210015
3100154
100100
51000
1000
65000
5000
75000
5000
8100000
100000
9100000
100000
10100000
100000
【樣例輸入】
5 2【樣例輸出】如果需要用到較大的棧空間。1 22 3
2 42 5
1 53 4
可以在編譯命令加上-wl,--stack=2333333333
。評測時開棧。
受洛谷p1967 貨車運輸啟發,這題很像lca。
於是我們就嘗試切lca。
首先,不難發現阻斷lca是可行的,那麼是最優的嗎?
對於一顆子樹內的點,如果從該子樹的點要延伸出子樹外,那必須經過最頂端的點。
如圖,對於乙個點,若要與外面有聯絡,那必定要經過\(lca(a,b)\)。
那兩點的聯絡在子樹內呢?如果是\(c\to d\),那顯然是無關的,那\(e\to b\)呢?我們發現最優應該切\(lca(e, b)\)。
那不是就wa了嗎?不。我們發現:如果我們先切\(lca(e, b)\),到\(a\to b\)是特判一下即可。
由於資料很水,判是否聯通用暴力爬就可以了。
下面上**,剛學樹剖,於是就打了個樹剖。
#include #include using namespace std;
const int maxn = 100005;
struct edge
e[maxn<<1];
int first[maxn];
int nowm;
inline void add_edge(int from, int to)
int fa[maxn], son[maxn], dep[maxn], val[maxn];
inline void dfs1(int x)//找重鏈,標記深度與父親
}int top[maxn];
inline void dfs2(int x, int ff)//尋找重鏈的頂端
}inline void init(int s)
inline int lca(int a, int b)
return dep[a] < dep[b] ? a : b;
}struct sxd
} ask[maxn];
bool biao[maxn];
inline bool pan(int a, int b)
int main()
init(1);
for(int i = 1; i <= m; ++i)
sort(ask+1, ask+m+1);//將提問排序,從下往上阻斷
int ans = 0;
for(int i = 1; i <= m; ++i)//暴力往上爬……(竟不會t,還是最優解)
printf("%d\n", ans);
return 0;
}
Walk 解題報告
給定一棵 n 個節點的樹,每條邊的長度為 1 同時有乙個權值 w 定義一條路徑的權值為路徑上所有邊的權值的最大公約數。現在對於任意 i in 1,n 求樹上所有長度為 i 的簡單路徑中權值最大的是多少。如果不存在長度為 i 的路徑,則第 i 行輸出 0 第一行,乙個整數 n 表示樹的大小。接下來 n...
騎車與走路
問題描述 在北大校園裡,沒有自行車,上課辦事很不方便,但實際上,並非去辦任何事情都是騎車快,因為騎車總是要找車,開鎖,停車,鎖車,這要耽誤一些時間 假設找到自行車的時間27秒,停車鎖車的時間為23秒 步行每秒1.2公尺,騎車每秒3.0公尺,請判斷坐不同的距離去辦事,是騎車快還是走路快。關於輸入 第一...
騎車與走路
描述 在北大校園裡,沒有自行車,上課辦事會很不方便.但實際上,並非去辦任何事情都是騎車快,因為騎車總要找車 開鎖 停車 鎖車等,這要耽誤一些時間.假設找到自行車,開鎖並車上自行車的時間為27秒 停車鎖車的時間為23秒 步行每秒行走1.2公尺,騎車每秒行走3.0公尺。請判斷走不同的距離去辦事,是騎車快...