codevs1700 施工方案第二季

题目描述 Description

c国边防军在边境某处的阵地是由n个地堡组成的。工兵连受命来到阵地要进行两期施工。

第一期的任务是挖掘暗道让所有地堡互联互通。现已勘测设计了m条互不相交的暗道挖掘方案,如果这m条暗道都实施挖掘,肯定能达到互联互通的目的。事实上,适当选择其中n-1个方案挖掘,就能实现互联互通,即从每个地堡出发都能到达其他任何一个地堡(允许经过别的地堡)。

连长精心谋算,在m个设计规划中选取了挖掘总距离最短且能保证互联互通的若干个暗道规划实施了挖掘,完成了第一期的施工任务后又接受了第二期的施工任务,要求选择一个地堡进行扩建改造,使其能向每个地堡提供弹药。为了让弹药供应更及时、更快捷,从改扩建的地堡到最远地堡的距离(称为最远输送距离)应当尽量小。

你的任务是先求出第一期施工挖掘的总距离,再求改扩建地堡最远输送距离的最小值。

输入描述 Input Description

其中第一行是n和m,m>=n
下面的m行每行3个数xi、yi、zi,表示xi到yi的距离是zi
  zi<1000000且m个距离互不相等

输出描述 Output Description

共包含两行,每行一个整数,
第一行是第一期的挖掘总距离,第二行是最远输送距离的最小值。

样例输入 Sample Input

4 5
1 2 1
2 3 2
3 4 3
4 1 4
3 1 5

样例输出 Sample Output

6
3

数据范围及提示 Data Size & Hint

【样例说明】
第一期挖掘1到2、2到3和3到4的3条暗道,第二期选择3号地堡进行改扩建,最远输送距离是3
【数据规模】
60%的数据 n<10且m<20
80%的数据 n<1000且m<2000
100%的数据 n<100000且m<200000

________________________________________________________________________________________________________________

树形动归

点i到大最远的点有两种可能,要么是它下面的叶子,也就是向西走,要么在父亲方向,也就是向上走。

向下的方向f[i]=max(f[j]+e[i->j].w)

向上的方向ff[i]=max(ff[fa[i]],f[son[fa[i](不是i点)])+e[i->fa[i]].w 

_________________________________________________________________________________________________________________

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int maxn=100005;
 4 const int maxm=200010;
 5 int n,m;
 6 struct edge
 7 {
 8     int u,v,w,nxt;
 9 }e[maxm<<1],ee[maxm];
10 int head[maxn],js;
11 void addage(int u,int v,int w)
12 {
13     e[++js].u=u;e[js].v=v;e[js].w=w;
14     e[js].nxt=head[u];head[u]=js;
15 }
16 int fa[maxn];
17 long long ans;
18 int find(int x)
19 {
20     if(fa[x]==x)return x;
21     return fa[x]=find(fa[x]);
22 }
23 bool un(int u,int v)
24 {
25     u=find(u),v=find(v);
26     if(u==v)return 0;
27     fa[v]=u;
28     return 1;
29 }
30 long long dl1[maxn],dl2[maxn],ul[maxn];
31 void dfs(int u,int fa)
32 {
33     for(int i=head[u];i;i=e[i].nxt)
34     {
35         int v=e[i].v;
36         if(v!=fa)
37         {
38             dfs(v,u);
39             if(dl1[v]+e[i].w>dl1[u])dl2[u]=dl1[u],dl1[u]=dl1[v]+e[i].w;
40             else if(dl1[v]+e[i].w>dl2[u])dl2[u]=dl1[v]+e[i].w;
41         }
42     }
43 }
44 void dfs2(int  u,int fa)
45 {
46     for(int i=head[u];i;i=e[i].nxt)
47     {
48         int v=e[i].v;
49         if(v!=fa)
50         {
51             if(dl1[v]+e[i].w==dl1[u])ul[v]=dl2[u];
52             else ul[v]=dl1[u];
53             if(ul[u]>ul[v])ul[v]=ul[u];
54             ul[v]+=e[i].w;
55             dfs2(v,u);
56         }
57     }
58 }
59 bool mycp(edge a,edge b)
60 {
61     return a.w<b.w;
62 }
63 int main()
64 {
65     scanf("%d%d",&n,&m);
66     for(int i=1;i<=n;++i)fa[i]=i;
67     for(int u,v,w,tp=0,i=0;i<m;++i)
68     {
69         scanf("%d%d%d",&u,&v,&w);
70         ee[i].u=u;ee[i].v=v;ee[i].w=w;
71         
72     }
73     sort(ee,ee+m,mycp);
74     for(int i=0;i<m;++i)
75     {
76         int u=ee[i].u,v=ee[i].v,w=ee[i].w;
77         if(un(u,v))
78         {
79             ans+=w;
80             addage(u,v,w);
81             addage(v,u,w);
82         }
83     }
84     dfs(1,0);
85     dfs2(1,0);
86     long long ans2=0x7ffffffffffffff;
87     for(int i=1;i<=n;++i)
88     {
89         int tp=max(ul[i],dl1[i]);
90         ans2=ans2<tp?ans2:tp;
91     }
92     printf("%lld\n%lld",ans,ans2);
93     return 0;
94 }
View Code

 

posted on 2018-10-24 17:03  gryzy  阅读(151)  评论(0编辑  收藏  举报

导航