http://codevs.cn/problem/1700/
2012年市队选拔赛北京
时间限制: 1 s
空间限制: 128000 KB
题目等级 : 黄金 Gold
查看运行结果
题目描述 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
第一问:最小生成树可求
第二问:树上距离最远的两点的路径为直径,显然将城堡在直径上的点扩建最优
(记录从直径某一段点,到直径上每点的距离,则ans=min(ans,val[t]-val[u])
1 #include <algorithm> 2 #include <cstring> 3 #include <cstdio> 4 5 #define LL long long 6 #define max(a,b) (a>b?a:b) 7 #define min(a,b) (a<b?a:b) 8 inline void read(int &x) 9 { 10 x=0; register char ch=getchar(); 11 for(; ch>‘9‘||ch<‘0‘; ) ch=getchar(); 12 for(; ch>=‘0‘&&ch<=‘9‘; ch=getchar()) x=x*10+ch-‘0‘; 13 } 14 const int N(100000+5); 15 const int M(200000+5); 16 int n,m,head[N],sumedge; 17 struct Edge { 18 int v,next,w; 19 Edge(int v=0,int next=0,int w=0):v(v),next(next),w(w){} 20 }edge[N<<1]; 21 struct Road { 22 int u,v,w; 23 bool operator < (const Road x)const 24 { 25 return w<x.w; 26 } 27 Road(int u=0,int v=0,int w=0):u(u),v(v),w(w){} 28 }road[M]; 29 inline void ins(int u,int v,int w) 30 { 31 edge[++sumedge]=Edge(v,head[u],w); 32 head[u]=sumedge; 33 } 34 35 int fa[N]; 36 int find(int x) 37 { 38 return x==fa[x]?x:fa[x]=find(fa[x]); 39 } 40 inline LL K_for_get_road() 41 { 42 int cnt=0; 43 LL ret=0; 44 std::sort(road+1,road+m+1); 45 for(int i=1; i<=n; ++i) fa[i]=i; 46 for(int fx,fy,i=1; i<=m; ++i) 47 { 48 fx=find(road[i].u),fy=find(road[i].v); 49 if(fx==fy) continue; 50 fa[fx]=fy; ret+=(LL)road[i].w; 51 ins(road[i].u,road[i].v,road[i].w); 52 ins(road[i].v,road[i].u,road[i].w); 53 if(++cnt==n-1) return ret; 54 } 55 return ret; 56 } 57 58 LL val[N],ans; 59 int s,t,pre[N]; 60 void DFS(int u) 61 { 62 for(int x,v,i=head[u]; i; i=edge[i].next) 63 { 64 v=edge[i].v; 65 if(v==pre[u]) continue; 66 val[v]=val[u]+(LL)edge[i].w; 67 pre[v]=u; DFS(v); 68 } 69 } 70 void Get(int u) 71 { 72 if(pre[u]) Get(pre[u]); 73 ans=min(ans,max(val[u],val[t]-val[u])); 74 } 75 76 int Presist() 77 { 78 read(n),read(m); 79 for(int u,v,w,i=1; i<=m; ++i) 80 read(u),read(v),read(w),road[i]=Road(u,v,w); 81 printf("%lld\n",K_for_get_road()); 82 83 DFS(s=1); 84 for(int i=1; i<=n; ++i) if(val[i]>val[s]) s=i; 85 memset(val,0,sizeof(val)); 86 memset(pre,0,sizeof(pre)); 87 DFS(s);t=1; 88 for(int i=1; i<=n; ++i) if(val[i]>val[t]) t=i; 89 ans=val[t]; Get(t); 90 printf("%lld\n",ans); 91 return 0; 92 } 93 94 int Aptal=Presist(); 95 int main(){;}