話說寧波市的中小學生在鎮海中學參加計算機程式設計比賽,比賽之餘,他們在鎮海中學的各個景點參觀。鎮海中學共有n個景點,每個景點均有若干學生正在參觀。這n個景點以自然數1至n編號,每兩個景點的編號均不同。每兩個景點之間有且只有一條路徑。選擇哪個景點集中的學生,才能使所有學生走過的路徑之和最小呢?
如果存在多個解,則輸出距離1最近的那個點,可以證明答案唯一
輸入檔案center.in中有若干行:
第一行只有乙個正整數n,表示景點數。
第二行有n個1至1000間的整數,這n個整數間互相以乙個空格分隔。其中第i個整數表示第i個景點處的學生數。
第三行至第n+1行,每行有三個整數i,j,k,表示景點i和景點j之間有一條長尾k的路徑直接連線。其中i<>j,1≤i≤n,1≤j≤n;1≤k≤1000。
輸出檔案center.out中有二行;
第一行只有乙個整數i,表示在第i個景點處集中時,所有學生走過的路徑之和最短。
第二行也只有乙個整數,表示所有學生走過的路徑之和的最小值。
所有的資料均隨機生成,且滿足:
30%的資料,1≤n≤200。
60%的資料,1≤n≤3000。
100%的資料,1≤n≤100000。
這題我沒想到什麼好的方法,主要是靠樹形dp推出每個點為集中點時的代價。
首先,我們需要乙個初始值,所以我們先暴力將1為集合點時的代價給求出來。
然後我們處理它的子節點
不難發現,子節點與原根節點的連邊是條很重要的邊
以該子節點為根的子樹的每乙個節點到集中點的貢獻都減少了該邊長度,而其他的邊都增加了該邊長度
所以我們就可以先在第一次暴力求答案的時候先求出幾個重要的數
首先我們設tree[i]表示以i為根的子樹的學生數
設f[i]表示該點到集中點的貢獻
一開始我們求出了f[1],而其他的點都可以推出來,最後求個最小值即可
#include
#define ll long long
using
namespace std;
int len,n,a,b,c,i,ans,go[
1000001
],to[
1000001
],last[
1000001
],w[
1000001
],tree[
1000001
],m[
1000001];
ll f[
1000001];
void
make
(int x,
int y,
int z)
voiddg(
int x,
int fa,ll s1)
k=to[k];}
}void
dfs(
int x,
int fa,ll s)
int k=last[x]
;while
(k)}
intmain()
for(i=
1;i(1,0
,0);
ans=1;
dfs(1,
0,0)
;printf
("%d\n%lld"
,ans,f[ans]);
}
149 快取網路資料
如果我們不快取網路資料 那麼每次切換頁面或者連線網路等情況 都要重複地去載入資料 這樣非常的消耗網路資源,記憶體資源 載入過的網路資料我們就不要去重複載入了 快取一下不就好了嗎 我們獲取到json 資料之後 就把json 資料儲存到 sp裡面 override public void onrespo...
149 直線上最多的點數
思路 先用map將輸入的點去重 這裡要自定義比較函式 然後對於每乙個點,遍歷其後面的每乙個點,記錄在一條直線上的點的數目,在記錄的過程中維護最大值。開始時在map的自定義比較函式上面卡了殼,為此還得到codeblock這種ide除錯才看的出來,用vs的話比較函式少了const照樣能執行 defini...
149 校門外的樹1 0
校門外的樹 某校大門外長度為l的馬路上有一排樹,每兩棵相鄰的樹之間的間隔都是1公尺。我們可以把馬路看成乙個數軸,馬路的一端在數軸0的位置,另一端在l的位置 數軸上的每個整數點,即0,1,2,l,都種有一棵樹。由於馬路上有一些區域要用來建地鐵。這些區域用它們在數軸上的起始點和終止點表示。已知任一區域的...