10.30T3 换根

Description

  在幻想乡,藤原妹红是拥有不老不死能力的人类。虽然不喜欢与人们交流,妹红仍然保护着误入迷途竹林村民。由于妹红算得上是幻想乡最强的人类,对于她而言,迷途竹林的单向道路亦可以逆行。在妹红眼中,迷途竹林可以视为一个由N个路口(编号1..N),M条不同长度双向路连接的区域。妹红所在的红之自警队为了方便在迷途竹林中行动,绘制了一张特殊的迷途竹林地图,这张地图上只保留了N-1条道路,这些道路保证了任意两个路口间有且仅有一条路径,并且满足所有保留的道路长度之和最小,我们称这些道路为『自警队道路』。现在妹红打算在其中一个连接有多条『自警队道路』的路口设立根据地,当去掉这个根据地所在路口后,就会出现某些路口间无法通过『自警队道路』相互连通的情况,我们认为这时仍然能够通过『自警队道路』连通的路口属于同一个『区域』。妹红希望最后每个『区域』的『自警队道路』总长尽可能平均,请计算出她应该选择哪一个路口作为根据地。 
  下例中红色的路口为妹红选择的根据地,实线边表示『自警队道路』,绿色虚线边表示非『自警队道路』,数字表示边权,『自警队道路』中相同颜色的实线边代表属于同一个『区域』:

  

  (尽可能平均即权值最小,设每一块『区域』的路线总长为 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的边。

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 
【注意】
  保证不存在相同距离的线路,两个路口间可能出现多条路径,且任意点对间至少存在一条路径。
 
 
 
 
简单的预处理子树里面的权值和然后直接换根就可以了
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

posted @ 2018-10-30 20:23  saionjisekai  阅读(186)  评论(0编辑  收藏  举报