您的位置:首页 > 其它

codeforces 219D 树形dp

2013-09-13 22:34 423 查看
题目链接:http://codeforces.com/problemset/problem/219/D

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<vector>
#include<utility>
using namespace std;

const int maxn = 2*1e5+100;

int dp[maxn];  //dp[i]表示以i为根遍历全部的点的最小的权值。

struct Edge{
int u,v,w;
int next;
Edge(int u=0,int v=0,int w=0,int next=0): u(u), v(v), w(w), next(next) {}
}edges[maxn*2];
int head[maxn],cnt;
int sum;  //以1为根的树至少要修改的边数。
int ans;

void addedge(int u,int v){
edges[cnt] = Edge(u,v,0,head[u]);
head[u] = cnt++;
edges[cnt] = Edge(v,u,1,head[v]);
head[v] = cnt++;
}

void dfs1(int u,int fa){
for(int i=head[u];i!=-1;i=edges[i].next){
Edge& e = edges[i];
if(e.v == fa) continue;
sum += e.w;
dfs1(e.v,u);
}
}

void dfs2(int u,int fa){
for(int i=head[u];i!=-1;i=edges[i].next){
Edge& e = edges[i];
if(e.v == fa) continue;
if(e.w == 1) dp[e.v] = dp[u] - 1;   //由于父亲节点的dp[u]已经算出,只需要更新就是了。
else         dp[e.v] = dp[u] + 1;
ans = min(ans,dp[e.v]);
dfs2(e.v,u);
}
}

int main()
{
//freopen("E:\\acm\\input.txt","r",stdin);
int n;
cin>>n;
memset(head,-1,sizeof(head));
cnt = 0;

for(int i=1;i<n;i++){
int u,v;
scanf("%d %d",&u,&v);
addedge(u,v);
}
sum = 0;
dfs1(1,-1);
memset(dp,0,sizeof(dp));
dp[1] = sum;
ans = 0x3f3f3f3f;
ans = min(ans,dp[1]);
dfs2(1,-1);
printf("%d\n",ans);
for(int i=1;i<=n;i++){
if(dp[i] == ans)
printf("%d ",i);
}

}


View Code
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: