題意:一顆n個點的樹,n-1條邊,每條邊的權值為1,找到乙個點,使得所有點到這個點的距離之和最小。
思路:我們假設點1為根時,總花費為f[1],假設點2是點1的子節點,那麼f[2]=f[1]-點2的子節點個數+(n-點2的子節點個數),因為我們把根從1換到2的時候,2的子樹中節點貢獻全部-1,其他節點貢獻全部+1。所以我們以1位根節點dfs一遍,找出每個節點的子樹節點數量,再dfs算出以1為根時的代價花費,最後dfs算出每個點的花費,最後輸出最小花費點和最小花費就行了。主要是式子不好想。
#include
using
namespace std;
const
int n=
2e5+5;
const
int inf=
0x7fffffff
;const
int mod=
1e9+7;
const
int eps=
1e-6
;typedef
long
long ll;
typedef
unsigned
long
long ull;
#define ls p<<1
#define rs p<<1|1
#define fi first
#define se second
#define mp make_pair
#define pb push_back
#define pii pair
#define int long long
#define ios ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define endl '\n'
#define null null
int head[n]
,nxt[n]
,to[n]
,tot=0;
void
add(
int u,
int v)
int s[n]
,f[n]
;int
dfs(
int x,
int y)
return s[x];}
void
dfs2
(int x,
int y,
int z)
}int res,n,pos;
void
dfs3
(int x,
int y)
signed
main()
dfs(1,
0);for
(int i=head[1]
;i;i=nxt[i]
)dfs2
(to[i],1
,1);
for(
int i=head[1]
;i;i=nxt[i]
)dfs3
(to[i],1
);res=f[1]
;pos=1;
for(
int i=
1;i<=n;i++)}
cout<' '<}
洛谷P1395 會議 題解
題目 為什麼這個題會有圖論的標籤啊,雖然圖論也包括找樹的重心,可是這很容易讓人聯想到最短路,但不得不說,這是乙個典型的找樹的重心模板題。樹的重心是什麼?找到乙個點,其所有的子樹中最大的子樹節點數最少,則這個點便是樹的重心。而我們找樹的重心該怎麼找呢,我們可以從定義入手,我們可以搜尋。我們先設任意乙個...
洛谷 P1395 會議(樹的重心)
為什麼要找樹的重心呢?假設我們已經找到了樹的重心,如果把開會地點從重心向右移走,那麼對答案的貢獻就是 左邊的元素和 右邊的元素和。而因為是樹的重心,所以向右移走後左面的元素數量一定大於右面的元素數量,所以ans是比在重心的情況大的,所以最終我們選擇重心。include include include...
找素數的一點思考
2016.7.17 本文 均由c 編寫 經典的素數判定演算法是這樣 給定乙個正整數n,用2到sqrt n 之間的所有整數去除n,如果可以整除,則n不是素數,如果不可以整除,則n就是素數。所以求小於n的所有素數程式如下 include include using namespace std defin...