(纪念第一道完全自己想的树DP)CodeForces 219D Choosing Capital for Treeland

Choosing Capital for Treeland

time limit per test

3 seconds

memory limit per test

256 megabytes

input

standard input

output

standard output

The country Treeland consists of n cities, some pairs of them are connected with unidirectional roads. Overall there are n - 1 roads in the country. We know that if we don‘t take the direction of the roads into consideration, we can get from any city to any other one.

The council of the elders has recently decided to choose the capital of Treeland. Of course it should be a city of this country. The council is supposed to meet in the capital and regularly move from the capital to other cities (at this stage nobody is thinking about getting back to the capital from these cities). For that reason if city a is chosen a capital, then all roads must be oriented so that if we move along them, we can get from city a to any other city. For that some roads may have to be inversed.

Help the elders to choose the capital so that they have to inverse the minimum number of roads in the country.

Input

The first input line contains integer n (2 ≤ n ≤ 2·105) — the number of cities in Treeland. Next n - 1 lines contain the descriptions of the roads, one road per line. A road is described by a pair of integers si, ti (1 ≤ si, ti ≤ nsi ≠ ti) — the numbers of cities, connected by that road. The i-th road is oriented from city si to city ti. You can consider cities in Treeland indexed from 1 to n.

Output

In the first line print the minimum number of roads to be inversed if the capital is chosen optimally. In the second line print all possible ways to choose the capital — a sequence of indexes of cities in the increasing order.

Examples

Input

32 12 3

Output

02 

Input

41 42 43 4

Output

21 2 3 
/*
纪念自己第一道完全自己想出来的树DP!!!!

给n个城市,n-1单向道路,要从中选择一个首都,首都的要求是从首都能到达所有其他城市,如果这些单向路中的方向不合适,可以重修这条路;
问选择一个最合适的首都,是的修路的次数最少;

思路:建图时,将路标记正向为0,逆向为1,dp[u]表示以u为首都最少修的路,dfs出dp[1]然后就能得出一个状态转移方程dp[v]=dp[u]+(w?-1:1);
再用一次dfs就可以了
*/
#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<string.h>
#include<vector>
#define N 200010
#define INF 0x3f3f3f3f
using namespace std;
struct node
{
    int to,len;//下一个节点,长度
    node (int x,int y)
    {
        to=x;
        len=y;
    }
};
int n;
vector<node> edge[N*2];
int dp[N];
int ans=0;
int dfs1(int u,int p)
{
    for(int i=0;i<edge[u].size();i++)
    {
        int v=edge[u][i].to;
        int w=edge[u][i].len;
        if(v==p) continue;
        //cout<<"u="<<u<<" "<<"v="<<v<<" "<<"w="<<w<<endl;
        ans+=w;
        dfs1(v,u);
    }
    return ans;
}
void dfs2(int u,int p)
{
    for(int i=0;i<edge[u].size();i++)
    {
        int v=edge[u][i].to;
        int w=edge[u][i].len;
        if(v==p) continue;
        //cout<<"u="<<u<<" "<<"v="<<v<<" "<<"w="<<w<<endl;
        dp[v]=dp[u]+(w?-1:1);
        dfs2(v,u);
    }
}
int main()
{
    //freopen("in.txt","r",stdin);
    while(scanf("%d",&n)!=EOF)
    {
        memset(dp,0,sizeof dp);
        for(int i=0;i<=n;i++)
            edge[i].clear();
        int a,b;
        for(int i=1;i<=n-1;i++)
        {
            scanf("%d%d",&a,&b);
            edge[a].push_back(node(b,0));
            edge[b].push_back(node(a,1));//逆向走的话就得花费一次
        }
        int min=INF;
        ans=0;
        dp[1]=dfs1(1,-1);
        //cout<<"dp[1]="<<dp[1]<<endl;
        dfs2(1,-1);
        for(int i=1;i<=n;i++)
        {
            if(dp[i]<min)
                min=dp[i];
        }
        printf("%d\n",min);
        int flag=0;
        for(int i=1;i<=n;i++)
        {
            if(dp[i]==min)
            {
                printf(flag?" %d":"%d",i);
                flag=1;
            }
        }
        printf("\n");
    }
    return 0;
}
时间: 2025-01-02 15:25:57

(纪念第一道完全自己想的树DP)CodeForces 219D Choosing Capital for Treeland的相关文章

Codeforces 219D. Choosing Capital for Treeland (树dp)

题目链接:http://codeforces.com/contest/219/problem/D 树dp 1 //#pragma comment(linker, "/STACK:102400000, 102400000") 2 #include <algorithm> 3 #include <iostream> 4 #include <cstdlib> 5 #include <cstring> 6 #include <cstdio&

hdu 1520 Anniversary party(第一道树形dp)

传送门: http://acm.hdu.edu.cn/showproblem.php?pid=1520 Anniversary party Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 16376    Accepted Submission(s): 6241 Problem Description There is going to

第一道防线__SpringMVC配置拦截器

这几天在公司自己开发一个小系统,但是系统的安全性也得考虑,起初没注意,赶急就光关心业务逻辑和实现效果.最后老大一出手,就把最严重的问题指出来了,他说你这根本没安全性可言,于是我试着将公司使用的spring security框架拿过来,但是在这之前我又尝试配置一下springmvc的拦截器,也可以说是网站的第一道防线. 这里我就拿用户登录问题来说吧. 1.首先自己手动编写一个拦截器类(自定义拦截器类),伪代码如下: 1 public class LoginInterceptor implement

《windows程序设计》第一章,建议想学API的每天看一章

开始 壹佰软件开发小组  整理编译   本书介绍了在Microsoft Windows 98.Microsoft Windows NT 4.0和Windows NT 5.0下程序写作的方法.这些程序用C语言编写并使用原始的Windows Application Programming Interface(API).如在本章稍后所讨论的,这不是写作Windows程序的唯一方法.然而,无论最终您使用什么方式写作程序,了解Windows API都是非常重要的. 正如您可能知道的,Windows 98已

hdu 4405 概率dp 2012年金华亚洲网络赛--虽然水,但是是自己独立做的第一道概率dp

题目:http://acm.hdu.edu.cn/showproblem.php?pid=4405 e[i]:当前在位置i还需要走的步数期望 受刘汝佳的AC自动机那个后缀链接写法的启发,我的x[i]通过逆序算出来连续有"flight line "的时候,能到达的最远距离, rep(i,0,m) { scanf("%d%d",&xx,&yy); x[xx]=yy; } for(int i=n;i>=0;i--) if(x[i]!=-1 &

BZOJ1040:骑士(基环树DP)

Z国的骑士团是一个很有势力的组织,帮会中汇聚了来自各地的精英.他们劫富济贫,惩恶扬善,受到社会各界的赞扬.最近发生了一件可怕的事情,邪恶的Y国发动了一场针对Z国的侵略战争.战火绵延五百里,在和平环境中安逸了数百年的Z国又怎能抵挡的住Y国的军队.于是人们把所有的希望都寄托在了骑士团的身上,就像期待有一个真龙天子的降生,带领正义打败邪恶.骑士团是肯定具有打败邪恶势力的能力的,但是骑士们互相之间往往有一些矛盾.每个骑士都有且仅有一个自己最厌恶的骑士(当然不是他自己),他是绝对不会与自己最厌恶的人一同出

HDU6447 YJJ&#39;s Salesman 2018中国大学生程序设计竞赛 - 网络选拔赛1010 离散化+线段树+DP

YJJ's Salesman Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 253    Accepted Submission(s): 62 Problem Description YJJ is a salesman who has traveled through western country. YJJ is always on

uva 12452 Plants vs. Zombies HD SP (树DP)

Problem I: Plants vs. Zombies HD Super Pro Plants versus Zombies HD Super Pro is a game played not a grid, but on a connected graph G with no cycles (i.e., a tree). Zombies live on edges of the tree and chew through edges so that tree falls apart! Pl

ZOJ3632 线段树+DP

买西瓜吃,每个西瓜有两个参数,一个是p代表价格,一个是t代表能吃几天,要求n天每天都能吃西瓜,而且如果你今天买了,以前买的还没吃完 那么都得扔了,求最小花费,还真想不到用线段树+DP,最后看了一下别人的标题,想了一下,DP方程挺好推的,线段树也只是单点查询, #include<iostream> #include<cstdio> #include<list> #include<algorithm> #include<cstring> #inclu