首页 > 其他分享 >洛谷P3629 [APIO2010] 巡逻题解

洛谷P3629 [APIO2010] 巡逻题解

时间:2023-07-25 13:23:46浏览次数:47  
标签:head P3629 int 题解 APIO2010 tot v1 道路 ans

题目链接

P3629 [APIO2010] 巡逻 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

思路

n个村庄,n-1条道路,原图为树

1.若k=0(不修建道路)那么答案为(n-1)*2

 每个道路会走两遍

2.若k为1(修建一条道路)

设修建的道路(r1)所在的环长度为L

那么答案为(n-1)*2-L+2

可以看到r1所在环的道路只走了一次

所以答案为原答案-(环的长度-1(r1))-1(r1)

令答案最小,则是令环的长度最长

则道路应修建在直径的两个端点上

答案为(n-1)*2-直径的长度+1;

3.若k为2(修建2条道路)

 

由b、c可知(或者自己手推)两条道路所在环可能有公共边或无公共边

当无公共边时(如图b)

 

发现两条道路互不影响

当无公共边时(如图c)

 

由于要满足必须经过新建的道路正好一次,两个环重复的地方仍要经过两次

那么将第一次计算的直径所经过的边权变成-1,再第二次计算直径即可

综上

当k=1时ans=(n-1)*2-直径长+1;

当k=2时ans=(n-1)*2-第一次的直径长+1-第二次的直径长+1

代码

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 
 4 const int N=100005;
 5 
 6 int head[N],ne[N*2],v[N*2],w[N*2],tot=0;//链式前向星存图
 7 void add(int x,int y,int z){
 8     ne[++tot]=head[x];
 9     v[tot]=y;
10     w[tot]=z;
11     head[x]=tot;
12 }
13 
14 
15 int l,ans=0;
16 int fa[N];//存每个节点的父亲
17 
18 void dfs(int u,int ffa,int dis){
19     if(dis>ans){
20         ans=dis;
21         l=u;
22     }
23     for(int i=head[u];i;i=ne[i]){
24         if(v[i]==ffa) continue;
25         fa[v[i]]=u;
26         dfs(v[i],u,dis+w[i]);
27     }
28 }
29 
30 int f[N][2];
31 void solve(int u,int ffa){
32     for(int i=head[u];i;i=ne[i]){
33         int v1=v[i];
34         if(v1==ffa) continue;
35         solve(v1,u);
36         if(f[v1][0]+w[i]>=f[u][0]){
37             f[u][1]=f[u][0];
38             f[u][0]=f[v1][0]+w[i];
39         }
40         else if(f[v1][0]+w[i]>f[u][1]) f[u][1]=f[v1][0]+w[i];
41     }
42 }
43 
44 int main(){
45     int n,k;
46     scanf("%d %d", &n, &k);
47     for(int i=1;i<n;i++){
48         int x,y;
49         scanf("%d %d", &x, &y);
50         add(x,y,1);
51         add(y,x,1);
52     }
53     
54     dfs(1,0,0);
55     for(int i=1;i<=n;i++) fa[i]=0;
56     ans=0;
57     dfs(l,0,0);
58     //从直径的一端开始,将构成直径的边赋值为-1
59     while(fa[l]){
60         for(int i=head[l];i;i=ne[i]){
61             if(v[i]==fa[l]){
62                 w[i]=-1;
63                 if(i%2==0) w[i-1]=-1;
64                 else w[i+1]=-1;
65                 break;
66             }
67         }
68         l=fa[l];
69     }
70     if(k==1){
71         cout<<(n-1)*2-ans+1;
72         return 0;
73     }
74     int l1=ans;
75     
76     solve(1,0);
77     
78     ans=0;
79     for(int i=1;i<=n;i++) ans=max(ans,f[i][0]+f[i][1]);
80     cout<<n*2-l1-ans;
81     
82     return 0;
83 }

 

标签:head,P3629,int,题解,APIO2010,tot,v1,道路,ans
From: https://www.cnblogs.com/Idtwtei/p/17579644.html

相关文章

  • 题解 P1150 【Peter的烟】
    postedon2020-11-1410:00:20|under题解|source2023编者注:本篇题解的方法过于暴力,但是尊重历史。请不要太在意。—-教你们用栈做这道题原题传送门看到这题,第一反应是用stack做。我们可以把Peter手上的烟看作一个栈,一根烟就是一个元素,抽了\(n\)支烟就从栈里pop几个,......
  • 题解 P1008 【三连击】
    postedon2020-11-1217:25:10|under题解|source2023编者注:请尊重历史。本题正解是暴力枚举先引用我们老师的一句话:(无恶意)不会吧不会吧,不会还有人不会写三连击吧!废话不多说,开始解题:理解题目和做题思路P1008三连击题目链接:https://www.luogu.com.cn/problem/......
  • 题解 CF1501A 【Alexey and Train】
    postedon2021-03-1321:57:02|under题解|source简单模拟题,考验选手的读题能力和使用谷歌翻译的能力。先定义一个\(now=0\),我们最后算出来的结果为\(now\)。对于每个站(不包括第\(n\)站),我们需要加上\(3\)个部分:额外时间,now+=ex[i];第\(i-1\)站到第\(i\)站的时......
  • 题解 CF1501B 【Napoleon Cake】
    postedon2021-03-1617:42:06|under题解|source题目可以转化一下:给一个长为\(n\)的数组\(a\),请求出一个长为\(n\)的数组\(b\)。要求若\(a_i\)不为\(0\),则\([b_{i-a_i+1},b_i]\)这个区间要为\(1\)。知道这个题目意思就好办了。题目说\(n\leq2\times10^5\),......
  • 题解 CF1497C2 【k-LCM (hard version)】
    postedon2021-03-2009:09:40|under题解|source2023编者注:有一些链接点不进去,分别是cf1497c1的cf页面和https://www.cnblogs.com/caijianhong/p/Solution-cf1497c1.html此题与CF1497C1有异曲同工之妙。我们知道,\(\operatorname{lcm}(1,x)=x\),不难想到,\(\operato......
  • 题解 CF1497C1 【k-LCM (easy version)】
    postedon2021-03-2008:26:53|under题解|source看数据范围,\(1\leqT\leq10^4\),\(1\leqn\leq10^9\),显然是构造题。我们分三类讨论:\(n\bmod2=1\):显然可以先提出一个\(1\),再把\(n-1\)分成两半,\(\operatorname{lcm}(1,\frac{n-1}{2},\frac{n-1}{2})=\frac{n-1}{2}\le......
  • 题解 P7679 【[COCI2008-2009#5] JABUKA】
    postedon2021-07-0717:38:14|under题解|source设题目中分给每个朋友的苹果数为\(x\),显然有\(x\vertr\landx\vertg\),也就是\(x\vert\gcd(r,g)\)。我们都知道,如果\(a\timesb=c\),那\(a\)和\(b\)都是\(c\)的因数,也就是说因数都是成对出现的(注意特判完全平方......
  • 题解 P2229 【[HNOI2002]沙漠寻宝】
    postedon2021-06-0112:15:15|under题解|source这题一看就知道是个模拟。做模拟题的时候,一定要先确保你的程序能跑出正确的结果,再去想优化时间。这道题还是很简单的,让我们开始吧:读入我们把输入离线,拿string存起来。如果不离线,那loop就会很难处理,加大难度。intn;......
  • 题解 P2903 【[USACO08MAR]The Loathesome Hay Baler S】
    postedon2021-05-0320:50:49|under题解|source首先输入,记录一下哪个齿轮的位置在\((0,0)\),哪个在\((x_t,y_t)\)。接着,为了避免多次判断两个齿轮相切而超时,我们可以预处理一个\(link_{i,j}\),表示第\(i\)个齿轮是否和第\(j\)个齿轮相切。这部分直接\(O(n^2)\)暴......
  • 题解 P1538 【迎春舞会之数字舞蹈】
    postedon2021-06-0113:24:05|under题解|source给\(0\cdots9\)每个数字打表,打它在相应的位置有没有一划。然后把每个数字分成\(5\)部分,暴力输出即可。#include<cstdio>#include<cstring>usingnamespacestd;constchar*db[]={"-||||-","||"......