码迷,mamicode.com
首页 > 其他好文 > 详细

CodeForces - 219D 树形dp

时间:2017-11-04 19:25:20      阅读:116      评论:0      收藏:0      [点我收藏+]

标签:play   als   max   using   map   需要   out   最小   mod   

题意:有向树,要求找最小的需要修改边的方向的数目,使得该点能到达树上每一个点,并求出所有最小数目的点

解法:树形dp,先从1开始dfs一遍(dp【u】是以u为根 的子树需要修改的边数)转移方程如果是u->x,dp【x】+=dp【u】+1,否则dp【x】+=dp【u】,再把dp【i】的意义改成以u为根的需要修改的边数,重新dfs一遍,转移方程if:u->x,dp【x】=dp【u】+1,else:dp【x】=dp【u】-1

技术分享
#include<bits/stdc++.h>
#define fi first
#define se second
#define mp make_pair
#define pb push_back
#define pii pair<int,int>
#define C 0.5772156649
#define pi acos(-1.0)
#define ll long long
#define mod 1000000007
#define ls l,m,rt<<1
#define rs m+1,r,rt<<1|1

using namespace std;
using namespace __gnu_cxx;

const double g=10.0,eps=1e-7;
const int N=200000+10,maxn=60000+10,inf=0x3f3f3f3f;

vector<int>v[N];
map<int,int>m[N];
int dp[N];
void dfs(int u,int f)
{
    for(int i=0;i<v[u].size();i++)
    {
        int x=v[u][i];
        if(x==f)continue;
        dfs(x,u);
        if(m[u][x])dp[u]+=dp[x];
        else dp[u]+=dp[x]+1;
    }
}
void dfs1(int u,int f)
{
    for(int i=0;i<v[u].size();i++)
    {
        int x=v[u][i];
        if(x==f)continue;
        if(m[u][x])dp[x]=dp[u]+1;
        else dp[x]=dp[u]-1;
        dfs1(x,u);
    }
}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    int n;
    cin>>n;
    for(int i=1;i<n;i++)
    {
        int a,b;
        cin>>a>>b;
        v[a].pb(b);
        v[b].pb(a);
        m[a][b]=1;
    }
    dfs(1,-1);
    dfs1(1,-1);
    int minn=300000;
    for(int i=1;i<=n;i++)minn=min(minn,dp[i]);
    cout<<minn<<endl;
    for(int i=1;i<=n;i++)
        if(dp[i]==minn)
            cout<<i<<" ";
    return 0;
}
/************

************/
View Code

 

CodeForces - 219D 树形dp

标签:play   als   max   using   map   需要   out   最小   mod   

原文地址:http://www.cnblogs.com/acjiumeng/p/7783934.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!