题目链接:http://codeforces.com/contest/219/problem/D

题目大意:

  给定一个n个节点的数和连接n个节点的n - 1条有向边,现在要选定一个节点作为起始节点,从这个点出发需要能走到其余每个节点,途中必然要调整有向边的方向,请求出当选定哪些节点作为初始节点时,所要调整的有向边最少,输出最小调整的边数和这些节点。

分析:

  Hint:城市结构是树型结构。

代码如下:

 #include <bits/stdc++.h>
using namespace std; #define rep(i,n) for (int i = 0; i < (n); ++i)
#define For(i,s,t) for (int i = (s); i <= (t); ++i)
#define rFor(i,t,s) for (int i = (t); i >= (s); --i)
#define foreach(i,c) for (__typeof(c.begin()) i = c.begin(); i != c.end(); ++i)
#define rforeach(i,c) for (__typeof(c.rbegin()) i = c.rbegin(); i != c.rend(); ++i) #define pr(x) cout << #x << " = " << x << " "
#define prln(x) cout << #x << " = " << x << endl #define LOWBIT(x) ((x)&(-x)) #define ALL(x) x.begin(),x.end()
#define INS(x) inserter(x,x.begin()) #define ms0(a) memset(a,0,sizeof(a))
#define msI(a) memset(a,inf,sizeof(a))
#define msM(a) memset(a,-1,sizeof(a)) #define pii pair<int,int>
#define piii pair<pair<int,int>,int>
#define mp make_pair
#define pb push_back
#define fi first
#define se second inline int gc(){
static const int BUF = 1e7;
static char buf[BUF], *bg = buf + BUF, *ed = bg; if(bg == ed) fread(bg = buf, , BUF, stdin);
return *bg++;
} inline int ri(){
int x = , f = , c = gc();
for(; c<||c>; f = c=='-'?-:f, c=gc());
for(; c>&&c<; x = x* + c - , c=gc());
return x*f;
} typedef long long LL;
typedef unsigned long long uLL;
const int inf = 1e9 + ;
const LL mod = 1e9 + ;
const int maxN = 2e5 + ; struct Node{
vector< pii > next;
}; int n, ans;
// dp[i]表示以i号城市为首都所要反转的道路数
int dp[maxN];
int vis[maxN];
Node nodes[maxN];
queue< int > Q; // 求dp[x]
inline int dfs(int x) {
if(nodes[x].next.empty()) return ; int ret = ;
foreach(i, nodes[x].next) {
int y = i->fi, z = i->se;
if(vis[y]) continue;
vis[x] = ;
if(z == -) ++ret;
ret += dfs(y);
}
return ret;
} // 如果dp[i]已知,假设j号城市与i号城市相连,由于整个城市图是树形结构,
// 因此dp[j]与dp[i]除了他们的连线有分歧,其余应该反转的道路数量都是一样的
// 因此可由已算出来的1号城市为中心,向外做BFS
inline void bfs() {
ms0(vis);
vis[] = ;
Q.push();
ans = dp[]; while(!Q.empty()) {
int tmp = Q.front();
Q.pop(); foreach(i, nodes[tmp].next) {
int y = i->fi, z = i->se;
if(vis[y]) continue;
vis[y] = ;
dp[y] = dp[tmp] + z;
ans = min(ans, dp[y]);
Q.push(y);
}
}
} int main(){
while(cin >> n) {
ms0(vis);
rep(i, n + ) nodes[i].next.clear();
rep(i, n-) {
int x, y;
cin >> x >> y;
nodes[x].next.push_back(mp(y, ));
nodes[y].next.push_back(mp(x, -));
}
dp[] = dfs(); bfs(); cout << ans << endl;
For(i, , n) if(ans == dp[i]) cout << i << " ";
cout << endl;
}
return ;
}

CodeForces 219D Choosing Capit的更多相关文章

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

    题目链接:http://codeforces.com/contest/219/problem/D 树dp //#pragma comment(linker, "/STACK:10240000 ...

  2. Codeforces 219D Choosing Capital for Treeland

    http://codeforces.com/problemset/problem/219/D 题目大意: 给出一棵树,但是它的边是有向边,选择一个城市,问最少调整多少条边的方向能使一个选中城市可以到达 ...

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

    Choosing Capital for Treeland time limit per test 3 seconds memory limit per test 256 megabytes inpu ...

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

    http://codeforces.com/problemset/problem/219/D 题意 给一颗树但边是单向边,求至少旋转多少条单向边的方向,可以使得树上有一点可以到达树上任意一点,若有多个 ...

  5. Codeforces 219D Choosing Capital for Treeland:Tree dp

    题目链接:http://codeforces.com/problemset/problem/219/D 题意: 给你一棵树,n个节点. 树上的边都是有向边,并且不一定是从父亲指向儿子的. 你可以任意翻 ...

  6. Codeforces 219D Choosing Capital for Treeland(树形DP)

    题目是给一张边有向的树形图.要选出首都的点,首都要都能走到其他点,因此要反转一些边的方向.问可以选哪几个点作为首都,使它们所需反转边的数量最少. 这题挺好想的,因为做过HDU2196. 首先就不妨设正 ...

  7. Codeforces 219D Choosing Capital for Treeland 2次DP

    //选择一个根使得变换最少边的方向使得能够到达所有点#include <map> #include <set> #include <list> #include & ...

  8. CodeForces 219D Choosing Capital for Treeland (树形DP)

    题意:给一个树形图,n个节点,n-1条有向边,要求选一个节点作为根,使需要改变方向的边的数目最少.并输出所有可能作为根的点. 思路: 先随便一个点进行DFS,计算将每棵子树的边全部往下时,所需要的费用 ...

  9. CodeForces 219D Choosing Capital for Treeland (树形DP)经典

    <题目链接> 题目大意: 给定一个有向树,现在要你从这颗树上选一个点,使得从这个点出发,到达树上其它所有点所需翻转的边数最小,输出最少需要翻转的边数,并且将这些符合条件的点输出. 解题分析 ...

随机推荐

  1. 【学习笔记】tensorflow实现一个简单的线性回归

    目录 准备知识 Tensorflow运算API 梯度下降API 简单的线性回归的实现 建立事件文件 变量作用域 增加变量显示 模型的保存与加载 自定义命令行参数 准备知识 Tensorflow运算AP ...

  2. .NET MVC 简单的插件式开发

    插件式开发的优势 1.提高软件的复用度 2.提高软件开发的并行性 3.缩短软件的研发周期.节约研发成本,带给程序开发人员更多的灵活性,产品在软件发布以后还可以添加新的插件和完善已有的功能. 4.方便软 ...

  3. 设计模式总结(Java)—— 观察者模式

    概述 它用于建立一种对象与对象之间的依赖关系,一个对象发生改变时将自动通知其他对象,其他对象将相应作出反应.在观察者模式中,发生改变的对象称为观察目标,而被通知的对象称为观察者,一个观察目标可以对应多 ...

  4. ios屏幕怎么投屏到电脑显示器

    iphone在国内一直都很受欢迎,为什么这么受欢迎呢?其实苹果手机操作系统非常的新颖,让人对手机有了重新的认识.但是ios屏幕怎么投屏到电脑显示器.感兴趣的一起阅读下面的内容吧! 使用工具: 苹果手机 ...

  5. ASP.NET C# 连接 Oracle数据库增删改查,事务

    一.知识介绍 ①ASP.NET 使用的是MVC模式,开发工具Visual studio ,语言C# ②Oracle是比较重型的数据库,这里主要介绍连接数据库,对数据进行具体的使用 ③Visual St ...

  6. TCP/IP、UDP、HTTP、SOCKET详解

    文章大纲 网络OSI七层及各层作用 TCP与UDP基本介绍 TCP连接过程详解 SOCKET原理与连接详解     一.网络OSI七层及各层作用   应用层:文件传输,电子邮件,文件服务,虚拟终端 T ...

  7. 基于Git项目管理客户端SourceTree的免注册安装及远程连接方法

    作为程序员,不可避免的要在github上查询代码,而在企业项目中,为了使得项目好管理需要使用项目管理客户端,所以接下来详细讲解一下基于git的sourceTree在windows系统下的安装及与Git ...

  8. 高端内存映射之vmalloc分配内存中不连续的页--Linux内存管理(十九)

    1 内存中不连续的页的分配 根据上文的讲述, 我们知道物理上连续的映射对内核是最好的, 但并不总能成功地使用. 在分配一大块内存时, 可能竭尽全力也无法找到连续的内存块. 在用户空间中这不是问题,因为 ...

  9. java8 快速实现List转map 、分组、过滤等操作

    利用java8新特性,可以用简洁高效的代码来实现一些数据处理. 定义1个Apple对象: public class Apple { private Integer id; private String ...

  10. MFC桌面电子时钟的设计与实现

    目录 核心技术 需求分析 程序设计 程序展示 (一)核心技术 MFC(Micosoft Foundation Class Libay,微基础类库)是微基于Windows平台下的C++类库集合,MFC包 ...