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. 【Network】一张图看懂 Reactor 与 Proactor 模型的区别

    首先来看看Reactor模式,Reactor模式应用于同步I/O的场景.我们以读操作为例来看看Reactor中的具体步骤:读取操作:1. 应用程序注册读就需事件和相关联的事件处理器2. 事件分离器等待 ...

  2. webdriver+python 对三大浏览器的支持

    1.在IE浏览器上运行测试脚本,首先需要下载IEDriverServer.exe(http://code.google.com/p/selenium/downloads/list,根据浏览器的版本下载 ...

  3. HAST 使用笔记

    1.环境 2台 freebsd 9.2的机器,/home分区为260G,需要将其转为hast块设备 2.安装 (1)先umount /home,然后注释掉/etc/fstab上的/home记录: # ...

  4. C++ 通过WIN32 API 获取逻辑磁盘详细信息

    众所周知,在微软的操作系统下编写应用程序,最主要的还是通过windows所提供的api函数来实现各种操作的,这些函数通常是可以直接使用的,只要包含windows.h这个头文件, 下载源文件 今天我们主 ...

  5. FastReport安装说明(中文版)

    FastReport安装说明(中文版) 内容列表 I. IntroductionI. 介绍II. Manual installing of the FastReport packagesII. 手动安 ...

  6. c++ 继承 虚函数与多态性 重载 覆盖 隐藏

    http://blog.csdn.net/lushujun2011/article/details/6827555 2011.9.27 1) 定义一个对象时,就调用了构造函数.如果一个类中没有定义任何 ...

  7. 全排列(next_permutation)

    next_permutation函数既可用于非重排列也可用于重排列: #include <bits/stdc++.h> #define MAXN 200000+10 #define ll ...

  8. 创建型模式之Strategy模式

    应用场景 实现某一个功能有多种算法或者策略,我们可以根据环境或者条件的不同选择不同的算法或者策略来完成该功能.如编写排序算法,可以将这些算法写到一个类中,在该类中提供多个方法,每一个方法对应一个具体的 ...

  9. go编写简单的web服务器

    package main import ( "fmt" "log" "net/http" "strings" ) //h ...

  10. PHP版QQ互联OAuth示例代码分享

    )   {     $ch = curl_init();     if(! $flag) curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);     cu ...