/* *题目大意: * 在一棵有向树上,使任意一个点为cap,满足从这个cap能够到达所有点, * 条件是是你可以更改边的方向。求所有改边最小的cap. *解题思路: * 一开始直接暴力肯定是TLE,然后想到了可以从入度为0的点开始考虑, * 复杂度开始下降,但是明显随即数据很难搞定,接着想到了是不是 * 重复计算次数太多了。如何减少重复计算?想到这里就没有再细想, * 没想到恰恰这里就是关键,先计算好随意一个cap点的改边数量。之后 * 其它的点均可以由这个点来推算出。 */
View Code
#include <iostream> #include <stdio.h> #include <algorithm> #include <cmath> #include <cstring> #include <string> #include <vector> #include <map> #include <set> #include <utility> #include <memory.h> #include <stack> #include <queue> #include <deque> #include <time.h> #include <iomanip> #define pi 3.1415926535897932 #define abs(x) ((x)>0?(x):-(x)) #define sqr(x) ((x)*(x)) #define sci(x) scanf("%d",&x) #define scd(x) scanf("%lf",&x) #define pri(x) printf("%d",x) #define prd(x) printf("%lf",x) #define inf 0x3f3f3f3f #define fi first #define se second #define tr(container, iterator) for(typeof(container.begin()) iterator=container.begin(); it != container.end(); it++) #define all(x) x.begin(), x.end() #define y0 stupid_cmath #define y1 very_stupid_cmath #define ll long long #define pb push_back #define mp make_pair #define rep(it,a,b) for(int it=a;it<=b;++it) #define _rep(it,a,b) for(int it=a;it>=b;--it) using namespace std; const int MAXN = 200005; const int MAXE = 200005; typedef struct _node { int v, w; int next; }N; vector<int> ans; int Min; N edge[2 * MAXE]; int cntEdge, head[MAXN]; int dp[MAXN]; void init(int n) { Min = 0x7fffffff; cntEdge = 0; fill(dp, dp + n + 1, 0); fill(head, head + n + 1, -1); } void addEdge(int u, int v) { edge[cntEdge].v = v; edge[cntEdge].w = 0; edge[cntEdge].next = head[u]; head[u] = cntEdge++; edge[cntEdge].v = u; edge[cntEdge].w = 1; edge[cntEdge].next = head[v]; head[v] = cntEdge++; } void dfs1(int n, int p) { for(int f = head[n]; f != -1; f = edge[f].next) { if(edge[f].v != p) { if(edge[f].w) dp[1]++; dfs1(edge[f].v, n); } } } void dfs2(int n, int p) { for(int f = head[n]; f != -1; f = edge[f].next) { if(edge[f].v != p) { if(edge[f].w == 0) dp[edge[f].v] = dp[n] + 1; else dp[edge[f].v] = dp[n] - 1; dfs2(edge[f].v, n); } } } int main() { #ifndef ONLINE_JUDGE freopen("in.txt", "r", stdin); #endif int n; while(scanf("%d", &n) == 1) { init(n); int u, v; for(int i = 0; i < n - 1; i++) { scanf("%d %d", &u, &v); addEdge(u, v); } dfs1(1, 1); dfs2(1, 1); rep(i, 1, n) if(dp[i] < Min) { Min = dp[i]; ans.clear(); ans.push_back(i); } else if(dp[i] == Min) { ans.push_back(i); } printf("%d\n", Min); sort(ans.begin(), ans.end()); rep(i, 0, ans.size() - 1) { if(!i) printf("%d", ans[i]); else printf(" %d", ans[i]); } puts(""); } return 0; }