【BZOJ 1912】 [Apio2010]patrol 巡逻

来源:互联网 发布:淘宝实时访客 编辑:程序博客网 时间:2024/04/30 04:57

1912: [Apio2010]patrol 巡逻

Time Limit: 4 Sec Memory Limit: 64 MB
Submit: 669 Solved: 380
[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 1

1 2

3 1

3 4

5 3

7 5

8 5

5 6
Sample Output

11
HINT

10%的数据中,n ≤ 1000, K = 1;
30%的数据中,K = 1;
80%的数据中,每个村庄相邻的村庄数不超过 25;
90%的数据中,每个村庄相邻的村庄数不超过 150;
100%的数据中,3 ≤ n ≤ 100,000, 1 ≤ K ≤ 2。

树的直径。

①如果k=1,显然是要求树的直径(因为在环上的边只需要走一次)。

②如果k=2,我们需要求加入两条边组成的环最大。

换个角度来看,相当于第一次找到直径之后进行第二次寻找,如果第二次找直径包含第一次找到的边,那么这条边对总答案的贡献为1

所以只要在第一次直径之后把直径上的边权置为1,然后再找一次直径即可。

#include <iostream>#include <algorithm>#include <cstring>#include <cmath>#include <cstdlib>#include <cstdio>#define M 200005#define inf 0x3f3f3f3fusing namespace std;int from,to,h[M],d[M],ans2,p[M],f[M],k,n,tot;struct edge{    int y,ne,v;}e[M];void Addedge(int x,int y){    e[++tot].y=y;    e[tot].ne=h[x];    e[tot].v=1;    h[x]=tot;}void dfs(int x,int fa){    for (int i=h[x];i;i=e[i].ne)    {        int y=e[i].y;        if (y==fa) continue;        d[y]=d[x]+e[i].v;        p[y]=i;        f[y]=x;        dfs(y,x);    }}int Getdiameter(){       d[1]=0;    dfs(1,0);    from=0,to=0;    for (int i=1;i<=n;i++)        if (d[from]<d[i]) from=i;    d[from]=0;    p[from]=f[from]=0;    dfs(from,0);    for (int i=1;i<=n;i++)        if (d[to]<d[i]) to=i;    return d[to]-1;}void dfs2(int x,int fa){    int m1=-inf,m2=-inf;    for (int i=h[x];i;i=e[i].ne)    {        int y=e[i].y;        if (y==fa) continue;        dfs2(y,x);        d[y]+=e[i].v;        d[x]=max(d[x],d[y]);        if (d[y]>m1) m2=m1,m1=d[y];        else if (d[y]>m2) m2=d[y];    }    if (m1==-inf&&m2==-inf)        d[x]=0;    ans2=max(ans2,m1+m2-1);}int main(){    tot=1;    scanf("%d%d",&n,&k);    for (int i=1;i<n;i++)    {        int x,y;        scanf("%d%d",&x,&y);        Addedge(x,y),Addedge(y,x);    }    int ans=2*(n-1)-Getdiameter();    if (k==2)    {        int x=p[to];        while (x)        {            e[x].v=e[x^1].v=-1;            x=p[f[e[x].y]];        }        ans2=0;        for (int i=1;i<=n;i++)            d[i]=-inf;        dfs2(1,0);        ans-=ans2;    }    cout<<ans<<endl;    return 0;}

这里写图片描述

1 1
原创粉丝点击