Codeforces Round #216 (diy.2) C. Valera and Elections

来源:互联网 发布:java web action 编辑:程序博客网 时间:2024/05/16 09:11

题目链接:点击打开链接

题意:给一棵树,N-1条边的权值可以是1和2。要找包含权值为2的边的路径有几条,并

           记录这条路径中距离点1最远的点。

分析:

就是树形dp,或者说是树上的记忆化dfs。

开始写dfs,没有从叶子节点开始向前面统计,而是从前往后统计,这样导致统计的结果

有时候偏大。因为返回的时候所有的u都置0,然后这条路径上所有由权值为2的边到达的点

全部算在结果内。


正确的从后往前记录结果:

1、如果是叶子节点且是由权值为2的边到达,则返回1;否则返回0。

2、非叶子节点,如果他的儿子统计的值res为0而它又是通过权值为2的边访问,则return 1。

3、其余情况都return 0。


要注意res的初始化!

开始dfs(1,1),虚拟一个点,通过权值为1的边到点1。


感想:

知道了怎么用vector建邻接表存图。

而且vector数组也可以用memset清零呀~


#include<cstdio>#include<iostream>#include<cstring>#include<string>#include<algorithm>#include<stack>#include<queue>#include<cctype>#include<cstdlib>#include<cmath>#define INF 0x3f3f3f3f#define MAX 100010using namespace std;struct node{    int t;    int w;}ve[MAX];vector<node> a[MAX];int ans[MAX];bool vis[MAX];int u,cnt;int dfs(int x,int k){    int b,flag=0,r,res=0;    for(int i=0;i<a[x].size();i++)    {        b=a[x][i].t;        r=a[x][i].w;        if(vis[b]==0)        {            vis[b]=1;            flag=1;            res+=dfs(b,r);        }    }    if(!flag)    {        if(k==2)        {            ans[cnt++]=x;            return 1;        }        return 0;    }    if(res==0 && k==2)    {        ans[cnt++]=x;        return 1;    }    return res;}int main(){    int n,s,e,w,t,aaa;    while(scanf("%d",&n)!=EOF)    {        int c=0,aaa=0;        memset(vis,0,sizeof(vis));        memset(a,0,sizeof(a));        for(int i=1;i<n;i++)        {            scanf("%d%d%d",&s,&e,&w);            ve[c].w=w;            ve[c].t=e;            a[s].push_back(ve[c]);            c++;            ve[c].w=w;            ve[c].t=s;            a[e].push_back(ve[c]);        }        u=0;        cnt=0;        vis[1]=true;        aaa=dfs(1,1);        if(cnt==0)        {            printf("0\n");            continue;        }        printf("%d\n",cnt);        for(int i=0;i<cnt-1;i++)            printf("%d ",ans[i]);        printf("%d\n",ans[cnt-1]);    }    return 0;}