HDNOIP201206施工方案
难度级别:A; 运行时间限制:1000ms; 运行空间限制:51200KB; 代码长度限制:2000000B
试题描述

c国边防军在边境某处的阵地是由n个地堡组成的。工兵连受命来到阵地要进行两期施工。第一期的任务是挖掘暗道让所有地堡互联互通。

现已勘测设计了m条互不相交的暗道挖掘方案,如果这m条暗道都实施挖掘,肯定能达到互联互通的目的。

事实上,适当选择其中n-1个方案挖掘,就能实现互联互通,即从每个地堡出发都能到达其他任何一个地堡(允许经过别的地堡)。

连长精心谋算,在m个设计规划中选取了挖掘总距离最短且能保证互联互通的若干个暗道规划实施了挖掘,

完成了第一期的施工任务后又接受了第二期的施工任务,要求选择一个地堡进行扩建改造,使其能向每个地堡提供弹药。

为了让弹药供应更及时、更快捷,从改扩建的地堡到最远地堡的距离(称为最远输送距离)应当尽量小。

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

输入
其中第一行是n和m,m>=n,下面的m行每行3个数xi、yi、zi,表示xi到yi的距离是zi,zi<1000000且m个距离互不相等
输出
两行各一个整数,第一行是第一期的挖掘总距离,第二行是最远输送距离的最小值。
输入示例
4 5
1 2 1
2 3 2
3 4 3
4 1 4
3 1 5
输出示例
6
3
其他说明
第一期挖掘1到2、2到3和3到4的3条暗道,第二期选择3号地堡进行改扩建,最远输送距离是3;60%的数据 n<10且m<20,80%的数据 n<1000且m<2000,100%的数据 n<100000且m<200000
 
 

第一问水水哒,直接MST即可。

第二问有两种做法:

做法一:可以猜想改建的地堡在直径上,因此两遍BFS即可

这个解法为什么是对的呢?我有一个绝妙的证明,但这里地方太小写不下。

#include<cstdio>
#include<cctype>
#include<queue>
#include<cstring>
#include<algorithm>
#define rep(s,t) for(int i=s;i<=t;i++)
#define ren for(int i=first[x];i;i=next[i])
using namespace std;
inline int read() {
int x=,f=;char c=getchar();
for(;!isdigit(c);c=getchar()) if(c=='-') f=-;
for(;isdigit(c);c=getchar()) x=x*+c-'';
return x*f;
}
typedef long long LL;
const int maxn=;
const int maxm=;
struct Edge {
int u,v,w;
bool operator < (const Edge& ths) const {return w<ths.w;}
}e[maxm];
int n,m,pa[maxn];
int findset(int x) {return x==pa[x]?x:pa[x]=findset(pa[x]);}
LL ans1;
int first[maxn],to[maxn<<],next[maxn<<],dis[maxn<<],ToT;
void AddEdge(int u,int v,int w) {
to[++ToT]=v;dis[ToT]=w;next[ToT]=first[u];first[u]=ToT;
to[++ToT]=u;dis[ToT]=w;next[ToT]=first[v];first[v]=ToT;
}
int d[maxn],vis[maxn],p[maxn];
int bfs(int x) {
memset(vis,,sizeof(vis));
queue<int> Q;Q.push(x);vis[x]=;d[x]=;
while(!Q.empty()) {
x=Q.front();Q.pop();
ren if(!vis[to[i]]) vis[to[i]]=,Q.push(to[i]),d[to[i]]=d[x]+dis[i],p[to[i]]=x;
}
int ret=;
rep(,n) if(d[i]>d[ret]) ret=i;
return ret;
}
int main() {
n=read();m=read();
rep(,m) e[i].u=read(),e[i].v=read(),e[i].w=read();
rep(,n) pa[i]=i;
sort(e+,e+m+);
rep(,m) {
int x=findset(e[i].u),y=findset(e[i].v);
if(x!=y) pa[x]=y,AddEdge(e[i].u,e[i].v,e[i].w),ans1+=e[i].w;
}
printf("%lld\n",ans1);
int s=bfs(),t=bfs(s),x=t,ans2=1e9;
while(x!=s) {
ans2=min(ans2,max(d[t]-d[x],d[x]));
x=p[x];
}
printf("%d\n",ans2);
return ;
}

做法二:水水哒点分治就好啦。我们可以计算出每个点到其他点的最远距离,记为dp[i]。

当根节点为x时,我们可以更新所有子树的dp值与根节点的dp值,实现要正着反着各扫一遍。

#include<cstdio>
#include<cctype>
#include<queue>
#include<cstring>
#include<algorithm>
#define rep(s,t) for(int i=s;i<=t;i++)
#define ren for(int i=first[x];i;i=next[i])
using namespace std;
inline int read() {
int x=,f=;char c=getchar();
for(;!isdigit(c);c=getchar()) if(c=='-') f=-;
for(;isdigit(c);c=getchar()) x=x*+c-'';
return x*f;
}
typedef long long LL;
const int maxn=;
const int maxm=;
struct Edge {
int u,v,w;
bool operator < (const Edge& ths) const {return w<ths.w;}
}e[maxm];
int n,m,pa[maxn];
int findset(int x) {return x==pa[x]?x:pa[x]=findset(pa[x]);}
LL ans1;
int first[maxn],to[maxn<<],next[maxn<<],dis[maxn<<],ToT;
void AddEdge(int u,int v,int w) {
to[++ToT]=v;dis[ToT]=w;next[ToT]=first[u];first[u]=ToT;
to[++ToT]=u;dis[ToT]=w;next[ToT]=first[v];first[v]=ToT;
}
int f[maxn],vis[maxn],dp[maxn],s[maxn],root,size;
void getroot(int x,int fa) {
s[x]=;int maxs=;
ren if(!vis[to[i]]&&to[i]!=fa) {
getroot(to[i],x);
s[x]+=s[to[i]];maxs=max(maxs,s[to[i]]);
}
f[x]=max(maxs,size-s[x]);
if(f[x]<f[root]) root=x;
}
int mxdep,dep2,A[maxn];
void dfs(int x,int fa,int dep) {
dp[x]=max(dp[x],mxdep+dep);dep2=max(dep,dep2);
ren if(!vis[to[i]]&&to[i]!=fa) dfs(to[i],x,dep+dis[i]);
}
void solve(int x) {
vis[x]=;mxdep=;int TAT=;
ren if(!vis[to[i]]) {
A[TAT++]=i;dep2=;
dfs(to[i],,dis[i]);
mxdep=max(mxdep,dep2);
}
dp[x]=max(dp[x],mxdep);mxdep=;
while(TAT--) {
dep2=;dfs(to[A[TAT]],,dis[A[TAT]]);
mxdep=max(mxdep,dep2);
}
ren if(!vis[to[i]]) {
f[]=size=s[to[i]];getroot(to[i],root=);
solve(root);
}
}
int main() {
n=read();m=read();
rep(,m) e[i].u=read(),e[i].v=read(),e[i].w=read();
rep(,n) pa[i]=i;
sort(e+,e+m+);
rep(,m) {
int x=findset(e[i].u),y=findset(e[i].v);
if(x!=y) pa[x]=y,AddEdge(e[i].u,e[i].v,e[i].w),ans1+=e[i].w;
}
printf("%lld\n",ans1);
f[]=size=n;getroot(,root=);
solve(root);
int ans2=1e9;
rep(,n) ans2=min(ans2,dp[i]);
printf("%d\n",ans2);
return ;
}

其实我认为第二个做法才是正解

COJ262 HDNOIP201206施工方案的更多相关文章

  1. HDNOIP201206施工方案

    HDNOIP201206施工方案 难度级别:A: 运行时间限制:1000ms: 运行空间限制:51200KB: 代码长度限制:2000000B 试题描述 c国边防军在边境某处的阵地是由n个地堡组成的. ...

  2. codevs——1700 施工方案第二季

    1700 施工方案第二季 2012年市队选拔赛北京  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 黄金 Gold 题解       题目描述 Description c国边防 ...

  3. codevs 1700 施工方案第二季

    1700 施工方案第二季 2012年市队选拔赛北京  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 黄金 Gold 题解       题目描述 Description c国边防 ...

  4. CODEVS——T 1700 施工方案第二季

    http://codevs.cn/problem/1700/ 2012年市队选拔赛北京  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 黄金 Gold 题解  查看运行结果   ...

  5. codevs1700 施工方案第二季

    题目描述 Description c国边防军在边境某处的阵地是由n个地堡组成的.工兵连受命来到阵地要进行两期施工. 第一期的任务是挖掘暗道让所有地堡互联互通.现已勘测设计了m条互不相交的暗道挖掘方案, ...

  6. 浅谈自我对git的初步认识

    本学期我们新增了一门课程,那就是软件工程,不知道为什么,感觉有种莫名的高大上.哈哈!难道是这个名称太抽象了吗?这个问题我感觉到后来肯定就明白了. 第一次博客,感觉好紧张哦,嘿嘿!老师让我们谈谈对git ...

  7. codevs与noi做题改错本目录

    从2016.2.13开始: 1.  排序超时的问题---------目录:-测试习题 2.  超高精度乘法超时问题-----------目录:高精度计算 算法:快速傅里叶算法. 压位算法 3. 高精度 ...

  8. js 数据获取

    http://www.cnhan.com/shantui/templates/MC500/TP001/js/template.js var qiaoContent="0";//0默 ...

  9. 杂项-建模:BIM

    ylbtech-杂项-建模:BIM 建筑信息模型是建筑学.工程学及土木工程的新工具.建筑信息模型或建筑资讯模型一词由Autodesk所创的.它是来形容那些以三维图形为主.物件导向.建筑学有关的电脑辅助 ...

随机推荐

  1. 用Python操纵MySQL

    本例用Python操纵MySQL,从指定文件读取数据,并对数据进行处理,处理之后批量插入MySQL. 贴上代码: # -*- coding: gbk -*- import re import MySQ ...

  2. Objective-C中的instancetype和id区别

    目录(?)[-] 有一个相同两个不同相同 Written by Mattt Thompson on Dec 10th 2012 一什么是instancetype 二关联返回类型related resu ...

  3. 【leetcode】Excel Sheet Column Number

    Excel Sheet Column Number Related to question Excel Sheet Column Title Given a column title as appea ...

  4. Eclipse 项目红色叹号:Build Path Problem

    Description Resource Path Location TypeA cycle was detected in the build path of project 'shgl-categ ...

  5. mybatis的insert简单使用

  6. Java之IO操作总结

    所谓IO,也就是Input与Output的缩写.在java中,IO涉及的范围比较大,这里主要讨论针对文件内容的读写 其他知识点将放置后续章节 对于文件内容的操作主要分为两大类 分别是: 字符流 字节流 ...

  7. Android之查看网络图片和网页HTML

    网络编程是Android应用中很重要的一部分,本文主要讲述了利用HttpURLConnection获取网络图片和HTML的方法. 获取网络图片 public class MainActivity ex ...

  8. CentOS 6.5 下安装 Kibana5

    1. 导入Elastic PGP Key 执行命令 rpm --import https://artifacts.elastic.co/GPG-KEY-elasticsearch 2. 安装Kiban ...

  9. 关于Java异常和错误的几个问题

    1.Java中什么是Exception? 异常是Java传达给你的系统和程序错误的方式. 在java中,异常功能是通过实现比如Throwable,Exception,RuntimeException之 ...

  10. c++ 复习内容

    . ]) { sizeof(str)=? } :// 函数行参仅是一个指针 . Typedef struct s* tPs; tPs p3,p4;//相等 struct s*p3,struct s*p ...