CF219D Choosing Capital for Treeland 题解

CF219D Choosing Capital for Treeland 题解

题目链接:CF219D Choosing Capital for Treeland

题意:Treeland国有n个城市,这n个城市连成了一颗树,有n-1条道路连接了所有城市。每条道路只能单向通行。现在政府需要决定选择哪个城市为首都。假如城市i成为了首都,那么为了使首都能到达任意一个城市,不得不将一些道路翻转方向,记翻转道路的条数为k。你的任务是找到所有满足k最小的首都。

随便找一个点 r t rt rt 跑一遍dfs,求出这个 d p [ r t ] dp[rt] dp[rt] 的值

然后 d p [ u ] → d p [ v ] dp[u] \to dp[v] dp[u]dp[v] 的转移显然与 ( u , v ) (u,v) (u,v) 有关

判断一下然后转移一下就没了

题外话:真的离了谱了,我换电脑之前写的这篇文章没发博客上,然后今天20220606花了2小时用爬虫和自己写的比对程序搞了半天才发现(恼

代码:

#include <bits/stdc++.h>
using namespace std;
#define int long long
#define INF 0x3f3f3f3f3f3f3f3f
#define N (int)(2e5+15)
struct Edge
{
    int u,v,next;
}e[N<<1];
int n,dp[N];
int pos=1,head[N],r[N<<1];
void addEdge(int u,int v)
{
    e[++pos]={u,v,head[u]};
    head[u]=pos;
}
int dfs1(int u,int f)
{
    int res=0;
    for(int i=head[u]; i; i=e[i].next)
    {
        int v=e[i].v;
        if(v==f)continue;
        if(!r[i])++res;
        res+=dfs1(v,u);
    }
    return res;
}
void dfs2(int u,int f)
{
    dp[u]+=dp[f];
    for(int i=head[u]; i; i=e[i].next)
    {
        int v=e[i].v;
        if(v==f)continue;
        if(r[i])++dp[v];
        else --dp[v];
        dfs2(v,u);
    }
}
signed main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);cout.tie(0);
    // freopen("check.in","r",stdin);
    // freopen("check.out","w",stdout);
    cin >> n;
    for(int i=1,u,v; i<n; i++)
    {
        cin >> u >> v;
        addEdge(u,v);r[pos]=1;
        addEdge(v,u);
    }
    dp[1]=dfs1(1,0);int mn=INF;
    dfs2(1,0);
    for(int i=1; i<=n; i++)
        mn=min(mn,dp[i]);
    cout << mn << endl;
    for(int i=1; i<=n; i++)
        if(dp[i]==mn)cout << i << " ";
    return 0;
}

转载请说明出处

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值