P3629 [APIO2010]巡逻

原创 2018年04月16日 13:28:10

题目大意:

给你一颗树,要把所有点遍历一次后回到原点。为了减少移动次数,你可以自己加入K条边,然后尽可能减少要走的道路树。K只为1,或者2

思路:

很显然我们要对K进行分类讨论,K=1时,要使得走过的路最少,显然是找到树的直径。
那么对于K=2的时候呢,我们仔细思考一下就会发现,对于两条路重叠的部分,因为每个点一定要走,所以要多走一次。那么我们把直径上的边权值取反,再找出一条权值最大的路径,减掉就好了。不能用bfs求树的直径,要用dp

程序:

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<queue>
#include<cstring>
#define N 1000000
using namespace std;
int p,cmax,cnt,n,k,ans,o,x,s;
int dep[N],f[N],last[N],d[N],v[N];
queue<int>q;
struct data{int to,next,w,fr;}e[N];
void add(int x,int y,int w){
    e[++cnt].to=y; e[cnt].fr=x;e[cnt].w=w; e[cnt].next=last[x]; last[x]=cnt;
    e[++cnt].to=x; e[cnt].fr=y;e[cnt].w=w; e[cnt].next=last[y]; last[y]=cnt;
}

void bfs(int x){
    while (!q.empty()) q.pop();
    q.push(x);
    cmax=0;
    memset(dep,30,sizeof(dep));
    dep[x]=1;
    while (!q.empty()){
        int u=q.front();
        q.pop();
        for (int i=last[u];i;i=e[i].next)
        if (dep[e[i].to]==505290270){
            dep[e[i].to]=dep[u]+e[i].w;
            f[e[i].to]=i;
            if (dep[e[i].to]>cmax){
                cmax=dep[e[i].to];
                s=e[i].to;
                p=i;
            }
            q.push(e[i].to);
        }
    }
}


void dp(int x){
    v[x]=1;
    for (int i=last[x];i;i=e[i].next){
        int y=e[i].to;
        if (v[y]) continue;
        dp(y);
        o=max(o,d[x]+d[y]+e[i].w);
        d[x]=max(d[x],d[y]+e[i].w);
    }
}

int main(){
    scanf("%d%d",&n,&k);
    cnt=1;
    for (int i=1;i<=n-1;i++){
        int x,y;
        scanf("%d%d",&x,&y);
        add(x,y,1);
    }
    ans=(n-1)*2+k;
    bfs(1);
    o=p;

    bfs(s);
    while (1==1){
        ans-=e[p].w;
        e[p^1].w=-e[p^1].w;
        e[p].w=-e[p].w;
        if (p==(o^1)) break;
        p=f[e[p].fr];
    }
    if (k==2){
        o=0;
        dp(1);
        ans-=o;
    }
    printf("%d",ans);
}
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq872425710/article/details/79959420

bzoj 1912: [Apio2010]patrol 巡逻

1912: [Apio2010]patrol 巡逻 Time Limit: 4 Sec  Memory Limit: 64 MB Submit: 1007  Solved: 549 [Submi...
  • clover_hxy
  • clover_hxy
  • 2016-05-03 14:55:34
  • 419

【BZOJ 1912】 [Apio2010]patrol 巡逻

思路题+树的直径~
  • Regina8023
  • Regina8023
  • 2015-05-07 08:03:28
  • 1225

[BZOJ1912]APIO2010巡逻|树的直径

这题看完大概的做法也想到了。。就是找出两条最长的路径连成环嘛。。但是不能简单的这样考虑,因为找次长的时候并不是不能走最长的路径上的边,只是走了第一次就等于白走了,也就是不仅没有产生新的贡献反而抵消了第...
  • Tag_king
  • Tag_king
  • 2015-04-18 11:11:15
  • 395

【bzoj1912】[Apio2010] patrol 巡逻 树形dp

题目大意:给你一棵树,你可以连k条边(1 题目分析:对于一棵树来说,遍历所有的点最少需要将每条边走两次,即2*(n-1)。显然当k==1时将直径的两个端点相连,便可以使原来直径上的边减少1次...
  • Winchester_
  • Winchester_
  • 2016-07-21 13:43:20
  • 470

[BZOJ1912][Apio2010]patrol 巡逻(dfs+并查集+树形dp)

痛苦的事是不用一直去想的,因为是想忘也忘不掉的。
  • Clove_unique
  • Clove_unique
  • 2016-05-03 14:53:50
  • 569

1912: [Apio2010]patrol 巡逻

1912: [Apio2010]patrol 巡逻 Time Limit: 4 Sec  Memory Limit: 64 MB Submit: 1186  Solved: 644 [Submi...
  • CRZbulabula
  • CRZbulabula
  • 2016-09-11 12:04:09
  • 200

[Apio2010]patrol 巡逻

题目大意:
  • u012602144
  • u012602144
  • 2014-09-21 16:39:01
  • 400

BZOJ1912[Apio2010]patrol 巡逻

传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=1912 题解:嗯,这是一道很好的题。 转自:http://www.cnblogs.com/...
  • qq_29206999
  • qq_29206999
  • 2016-08-15 10:02:01
  • 107

bzoj1912 [Apio2010]patrol 巡逻(树的直径[变式])

Description Input 第一行包含两个整数 n, K(1 ≤ K ≤ 2)。接下来 n – 1行,每行两个整数 a, b, 表示村庄a与b之间有一条道路(1 ≤ a, b ≤ n)。O...
  • wu_tongtong
  • wu_tongtong
  • 2017-09-27 10:00:30
  • 82

BZOJ 1912 [Apio2010]patrol 巡逻

网络上大部分都是用最长链做的,但是我(因为太弱了)并不能理解这样的正确性。。。所以就打了个树形DP。k=1时,答案=2*(n-1)-最长链长度+1 k=2时,发现如果两条链相交,相交的部分并不能减一...
  • ziqian2000
  • ziqian2000
  • 2016-08-06 16:47:50
  • 141
收藏助手
不良信息举报
您举报文章:P3629 [APIO2010]巡逻
举报原因:
原因补充:

(最多只允许输入30个字)