列表

详情


DP57. 旅游

描述

Cwbc和XHRlyb生活在 s 市,这天他们打算一起出去旅游。
旅行地图上有 n 个城市,它们之间通过 n-1 条道路联通。
Cwbc和XHRlyb第一天会在 s 市住宿,并游览与它距离不超过 1 的所有城市,之后的每天会选择一个城市住宿,然后游览与它距离不超过 1 的所有城市。
他们不想住在一个已经浏览过的城市,又想尽可能多的延长旅行时间。
XHRlyb想知道她与Cwbc最多能度过多少天的时光呢?
聪明的你在仔细阅读题目后,一定可以顺利的解决这个问题!

输入描述

第一行,两个正整数n和s,表示城市个数和第一天住宿的城市s。
接下来n-1行,每行两个整数x和y,表示城市x与城市y之间有一条双向道路。

输出描述

第一行,一个非负整数表示答案。

示例1

输入:

4 1
1 2
2 3
3 4

输出:

2

说明:

第一天,在1号城市住宿,游览了1、2号城市。
第二天,在3号城市住宿,游览了4号城市,旅行结束。

原站题解

C++ 解法, 执行用时: 130ms, 内存消耗: 25848KB, 提交时间: 2021-11-26

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int N=1e6+1000;
int n,s,f[N][2];
int ver[N],nxt[N],head[N],tot;
inline void add(int x,int y)
{
    ver[++tot]=y;
    nxt[tot]=head[x];
    head[x]=tot;
}
inline void dfs(int x,int fa)
{
    f[x][1]=1;
    for(int i=head[x];i;i=nxt[i]){
        int y=ver[i];
        if(y==fa)continue;
        dfs(y,x);
        f[x][1]+=f[y][0];
        f[x][0]+=max(f[y][0],f[y][1]);
    }
}
int main()
{
    scanf("%d%d",&n,&s);
    for(int i=1;i<n;i++){
        int x,y;scanf("%d%d",&x,&y);
        add(x,y);add(y,x);
    }
    dfs(s,0);
    printf("%d",f[s][1]);
    return 0;
}

C++ 解法, 执行用时: 153ms, 内存消耗: 25720KB, 提交时间: 2022-01-26

#include<bits/stdc++.h>
using namespace std;
const int MAX_N=500000 + 5;
int n,s,f[MAX_N][2];
int Last[MAX_N],Next[MAX_N<<1],End[MAX_N<<1],tot;
void addedge(int x,int y){
    End[++tot]=y;
    Next[tot]=Last[x];
    Last[x]=tot;
}
void solve(int x,int fa){
    for(int i=Last[x];i;i=Next[i]){
        int y=End[i];
        if(y!=fa){
            solve(y,x);;
            f[x][1]+=f[y][0];
            f[x][0]+=max(f[y][0],f[y][1]);
        }
    }
    f[x][1]++;
}
int main(){
    scanf("%d%d",&n,&s);
    for(int i=1;i<n;i++){
        int x,y;
        scanf("%d%d",&x,&y);
        addedge(x,y);
        addedge(y,x);
    }
    solve(s,0);
    printf("%d\n",f[s][1]);
    return 0;
}

C++ 解法, 执行用时: 155ms, 内存消耗: 17656KB, 提交时间: 2021-11-12

#include <bits/stdc++.h>
using namespace std;
//邻接表纪录树 边的编号从1开始
const int N=500001;
struct L{
    int head[N]={},nxt[N<<1]={},v[N<<1]={},lh=0;
    void push(int h,int val){
        nxt[++lh]=head[h];head[h]=lh;
        v[lh]=val;
    }
}l1;
int main(){
    int n,s;cin>>n>>s;
    //输入路网
    for(int i=0;i<n-1;i++){
        int a,b;scanf("%d%d",&a,&b);
        l1.push(a, b);l1.push(b, a);
    }
    //根节点为s 开始树形dp
    int dp[N][2]={};//dp[i][0]表示不取的最大值 dp[i][1]表示取到的最大值
    //非递归解法:
    struct D{int father,cur;bool recf;}st[N];int sth=0;
    st[sth++]={0,s,0};
    while(sth){
        D&cur=st[sth-1];
        if(!cur.recf){
            cur.recf=1;
            for(int i=l1.head[cur.cur];i!=0;i=l1.nxt[i])
                if(l1.v[i]!=cur.father)
                    st[sth++]={cur.cur,l1.v[i],0};
        }else{
            int f=cur.father,i=cur.cur;
            dp[i][1]+=1;
            dp[f][0]+=max(dp[i][0],dp[i][1]);
            dp[f][1]+=dp[i][0];
            sth--;
        }
    }
    printf("%d",dp[s][1]);
    return 0;
}

C++ 解法, 执行用时: 162ms, 内存消耗: 25724KB, 提交时间: 2022-07-10

#include<iostream>
#include<vector>
#include <algorithm>
using namespace std;
const int N = 500000 + 5; 
const int M = N  << 1;
int  h[N], ne[M], e[M], idx;
int dp[N][2];
void add(int x, int y) {
    e[++idx] = y;
    ne[idx] = h[x];
    h[x] = idx;
}

void solve(int x, int from) {
    for (int i = h[x]; i; i = ne[i]) {
        int y = e[i];
        if (y != from) {
            solve(y, x);
            dp[x][1] += dp[y][0];
            dp[x][0] += max(dp[y][0], dp[y][1]);
        }
    }
    dp[x][1]++;
}
int main() {
    int n, s;
    cin >> n >> s;
    for(int i=1;i<n;i++){
        int x,y;
        scanf("%d%d",&x,&y);
        add(x,y);
        add(y,x);
    }
    solve(s, 0);
    printf("%d\n",dp[s][1]);
    return 0;
}

C 解法, 执行用时: 171ms, 内存消耗: 21804KB, 提交时间: 2021-12-07

#include <stdio.h>

int dp[500001][2]={[0 ... 500000]={0,1}};

int next_edge=0;
int head[500001]={[0 ... 500000]=-1};
struct {
    int value;
    int next;
}edge[1000002]={[0 ... 1000001]={0,-1}};

void addEdge(int x,int y)
{
    edge[++next_edge].value = y;
    edge[next_edge].next = head[x];
    head[x] = next_edge;
}

void dfs(int x,int father)
{
    for(int i=head[x];i!=-1;i=edge[i].next)
    {
        if(edge[i].value == father) continue;
        dfs(edge[i].value,x);
        dp[x][1] += dp[edge[i].value][0];
        dp[x][0] += dp[edge[i].value][0]>dp[edge[i].value][1]?dp[edge[i].value][0]:dp[edge[i].value][1];
    }
}

int main()
{
    int n,s,x,y;
    scanf("%d %d",&n,&s);
    for(int i=1;i<n;++i)
    {
        scanf("%d %d",&x,&y);
        addEdge(x,y);
        addEdge(y,x);
    }
    dfs(s,-1);
    printf("%d",dp[s][1]);

    return 0;
}

上一题