bzoj 1912: [Apio2010]patrol 巡逻
2016-05-03 14:55
323 查看
1912: [Apio2010]patrol 巡逻
Time Limit: 4 Sec Memory Limit: 64 MBSubmit: 1007 Solved: 549
[Submit][Status][Discuss]
Description
Input
第一行包含两个整数 n, K(1 ≤ K ≤ 2)。接下来 n – 1行,每行两个整数 a, b, 表示村庄a与b之间有一条道路(1 ≤ a, b ≤ n)。Output
输出一个整数,表示新建了K 条道路后能达到的最小巡逻距离。Sample Input
8 11 2
3 1
3 4
5 3
7 5
8 5
5 6
Sample Output
11HINT
10%的数据中,n ≤ 1000, K = 1;30%的数据中,K = 1;
80%的数据中,每个村庄相邻的村庄数不超过 25;
90%的数据中,每个村庄相邻的村庄数不超过 150;
100%的数据中,3 ≤ n ≤ 100,000, 1 ≤ K ≤ 2。
Source
[Submit][Status][Discuss]
题解:
先说明一个定义: 树的直径是一棵树上最长的一条路径,从树上任意一个点dfs出离他最远的一个点,再从这个点dfs出离他最远的点,两次dfs出的点之间的路径就是树上最长的链,即最长的一条路径。
k==1 因为要使走的重复的路尽可能的短,所以我们在添加一条边的时候就要保证形成的环中的边尽可能的多,也就是求树上的最长链。ans=2(n-1)-len1+1
k==2 这时候需要在1的基础上再求最长链,因为如果再形成的环与第一个环有重叠的话,那么重叠的部分还是会走两次,所以把第一遍走过的路径付成-1,再求树的直径即可。ans=2(n-1)-len1+1-len2+1
#include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> #define N 200003 using namespace std; int n,k; int point ,next ,v ,c ,tot=-1,ans,ansx; int last ,len1,len2; void add(int x,int y,int z) { tot++; next[tot]=point[x]; point[x]=tot; v[tot]=y; c[tot]=z; tot++; next[tot]=point[y]; point[y]=tot; v[tot]=x; c[tot]=z; } void dfs(int x,int fa,int dis,int num) { if (dis>ans) { ans=dis,ansx=x; } for (int i=point[x];i!=-1;i=next[i]) if (fa!=v[i]) { last[v[i]]=i; dfs(v[i],x,dis+c[i],i); } } void change(int s,int t) { int now=t; while (now!=s) { c[last[now]]=-1; c[last[now]^1]=-1; now=v[last[now]^1]; } } int dp(int x,int fa) { int first=0; int second=0; for (int i=point[x];i!=-1;i=next[i]) if (v[i]!=fa) { int t=c[i]+dp(v[i],x); if (t>first) { second=first; first=t; } else if (t>second) second=t; } if (first+second>ans) ans=first+second; return first; } int main() { scanf("%d%d",&n,&k); tot=-1; memset(point,-1,sizeof(point)); memset(next,-1,sizeof(next)); for (int i=1;i<n;i++) { int x,y; scanf("%d%d",&x,&y); add(x,y,1); } dfs(1,0,0,0); int head=ansx; ans=0; dfs(ansx,0,0,0); int tail=ansx; len1=ans; change(head,tail); if (k==1) { printf("%d\n",2*(n-1)-ans+1); return 0; } ans=0; dp(1,0); printf("%d\n",2*(n-1)-len1-ans+2); }
相关文章推荐
- 简单记录jsp
- AJAX-JQUERY
- 如何减少事实表的大小
- APP-用户登录以及信息传输设计
- MD5 加密 代码
- Android webview监听网页对话框点击事件
- 第2课:SparkStreaming 透彻理解三板斧之二:解密SparkStreaming运行机制和架构
- define_method跟def
- 外部系统调用SAP接口如何调试
- 一个简单的login方法
- Html5自学过程笔记
- 新买的电脑如何用U盘装系统
- How HashMap works in java
- UVa 11389 The Bus Driver Problem
- (OK) dnf——install docker on Fedora23
- new/delete operator、operator new/delete、placement new
- timeStamp2String
- invalidate()和postInvalidate() 的区别及使用
- [git]通过commit_id找回文件
- Android—— Animation动画(很详细)