10.30T3 换根
Description
在幻想乡,藤原妹红是拥有不老不死能力的人类。虽然不喜欢与人们交流,妹红仍然保护着误入迷途竹林村民。由于妹红算得上是幻想乡最强的人类,对于她而言,迷途竹林的单向道路亦可以逆行。在妹红眼中,迷途竹林可以视为一个由N个路口(编号1..N),M条不同长度双向路连接的区域。妹红所在的红之自警队为了方便在迷途竹林中行动,绘制了一张特殊的迷途竹林地图,这张地图上只保留了N-1条道路,这些道路保证了任意两个路口间有且仅有一条路径,并且满足所有保留的道路长度之和最小,我们称这些道路为『自警队道路』。现在妹红打算在其中一个连接有多条『自警队道路』的路口设立根据地,当去掉这个根据地所在路口后,就会出现某些路口间无法通过『自警队道路』相互连通的情况,我们认为这时仍然能够通过『自警队道路』连通的路口属于同一个『区域』。妹红希望最后每个『区域』的『自警队道路』总长尽可能平均,请计算出她应该选择哪一个路口作为根据地。
下例中红色的路口为妹红选择的根据地,实线边表示『自警队道路』,绿色虚线边表示非『自警队道路』,数字表示边权,『自警队道路』中相同颜色的实线边代表属于同一个『区域』:
(尽可能平均即权值最小,设每一块『区域』的路线总长为 Length[i],平均路线长度为Avg=SUM{Length[i]}/区域数,权值d=∑((Length[i]-Avg)^2))
下例中红色的路口为妹红选择的根据地,实线边表示『自警队道路』,绿色虚线边表示非『自警队道路』,数字表示边权,『自警队道路』中相同颜色的实线边代表属于同一个『区域』:
(尽可能平均即权值最小,设每一块『区域』的路线总长为 Length[i],平均路线长度为Avg=SUM{Length[i]}/区域数,权值d=∑((Length[i]-Avg)^2))
Input
第1行:2个正整数N,M。
第2..M+1行:每行2个整数u,v和1个实数len,表示u,v之间存在长度为len的边。
第2..M+1行:每行2个整数u,v和1个实数len,表示u,v之间存在长度为len的边。
Output
第1行:1个整数,最后选择的路口编号,存在多个可选路口时选择编号小的。
Sample Input
3 3
3 1 5
3 2 4
1 2 3
Sample Output
2
Hint
【样例解释】
妹红的『固定道路』为(1,2)和(2,3)。只能选择2作为根据地,产生的两个区域Length[i]分别为3和4,所以方差为:(4-3.5)^2+(3-3.5)^2=0.5
【数据范围】
对于60%的数据:3≤N≤2,000,N-1≤M≤50,000
对于100%的数据:3≤N≤40,000,N-1≤M≤200,000
对于100%的数据:0 < len ≤ 100,000,000
【注意】
保证不存在相同距离的线路,两个路口间可能出现多条路径,且任意点对间至少存在一条路径。
妹红的『固定道路』为(1,2)和(2,3)。只能选择2作为根据地,产生的两个区域Length[i]分别为3和4,所以方差为:(4-3.5)^2+(3-3.5)^2=0.5
【数据范围】
对于60%的数据:3≤N≤2,000,N-1≤M≤50,000
对于100%的数据:3≤N≤40,000,N-1≤M≤200,000
对于100%的数据:0 < len ≤ 100,000,000
【注意】
保证不存在相同距离的线路,两个路口间可能出现多条路径,且任意点对间至少存在一条路径。
简单的预处理子树里面的权值和然后直接换根就可以了
code:
1 #include<iostream> 2 #include<cstdio> 3 #include<cmath> 4 #include<algorithm> 5 #define N 100005 6 using namespace std; 7 struct node { 8 double u,v; 9 double w; 10 } e[N],t[N]; 11 int first[N],nxt[N],cnt; 12 void add(int u,int v,double w) { 13 e[++cnt].u=u; 14 e[cnt].v=v; 15 e[cnt].w=w; 16 nxt[cnt]=first[u]; 17 first[u]=cnt; 18 } 19 double f[N]; 20 double sumtree=0; 21 double find(int x) { 22 if(x!=f[x])return f[x]=find(f[x]); 23 return f[x]; 24 } 25 void merge(int x,int y) { 26 int f1=find(x),f2=find(y); 27 if(f1!=f2) { 28 f[f1]=f2; 29 } 30 } 31 int n,m; 32 void kruskal() { 33 double cnt_=0; 34 for(int i=1; i<=m; i++) { 35 double u=t[i].u,v=t[i].v; 36 if(find(u)!=find(v)) { 37 merge(u,v); 38 cnt_++; 39 add(u,v,t[i].w); 40 add(v,u,t[i].w); 41 sumtree+=t[i].w; 42 if(cnt_==n-1)return; 43 } 44 } 45 } 46 double siz[N]; 47 double fa[N]; 48 void dfs1(int x){ 49 siz[x]=0; 50 for(int i=first[x];i;i=nxt[i]){ 51 siz[x]+=e[i].w; 52 int v=e[i].v; 53 if(v==fa[x])continue; 54 fa[v]=x; 55 dfs1(v); 56 siz[x]+=siz[v]; 57 } 58 } 59 void dfs2(int x){ 60 double child[10005];int tot=0; 61 for(int i=first[x];i;i=nxt[i]){ 62 int v=e[i].v; 63 if(v==fa[x])continue; 64 child[++tot]=siz[v]+e[i].w; 65 } 66 if(tot==0)return; 67 if(x!=1){ 68 child[++tot]=sumtree-siz[x]; 69 } 70 double avg=sumtree/tot; 71 double d=0; 72 for(int i=1;i<=tot;i++){ 73 d+=(child[i]-avg)*(child[i]-avg); 74 } 75 if(d<min0) 76 } 77 bool cmp(const node&a,const node&b) { 78 return a.w<b.w; 79 } 80 int main() { 81 cin>>n>>m; 82 for(int i=1; i<=n; i++)f[i]=i; 83 for(int i=1; i<=m; i++) { 84 cin>>t[i].u>>t[i].v>>t[i].w; 85 } 86 sort(t+1,t+m+1,cmp); 87 kruskal();/// 88 dfs1(1); 89 dfs2(1); 90 cout<<ID; 91 return 0; 92 }
over