现在的位置: 首页 > 综合 > 正文

Codeforces Round #216 C Valera and Elections ( DFS )

2018年09月22日 ⁄ 综合 ⁄ 共 1149字 ⁄ 字号 评论关闭

题目链接:  
C

题目大意:   给出N(N<=10^5)个结点的树,树上某些路是需要维修的

                  选择某个结点,从这个结点出发到达1结点的路都会被修复

                  求这些结点的集合,使得这个集合最小并输出集合的结点(SPJ)

解题思路:  建立无向边,从1结点出发开始DFS,没遍历的点就遍历

                  回溯的时候记录这段路的第一条需要修复的边顶点加入集合

                  若该结点的孩子结点已经被加入集合,则不需要再加入集合

代码:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX 101000
struct snode{
    int to,w,next;
}Tree[MAX<<2];
int visit[MAX],pre[MAX],sum[MAX],Index,Answer[MAX],Ansn;

void Add_edge(int a,int b,int c)
{
    Tree[Index].w=c;Tree[Index].to=b;
    Tree[Index].next=pre[a];
    pre[a]=Index++;
}

int DFS(int Star,int w)
{
    visit[Star]=1;           //记录结点被访问过
    int i,v,pd=0,kk=0;
    for(i=pre[Star];i!=-1;i=Tree[i].next)
    {
        if(visit[Tree[i].to])
            continue;
        sum[Star]+=DFS(Tree[i].to,Tree[i].w);
    }
    if(w==2||sum[Star]>=1)   //若该条路需要被修复||子节点已经被修复
    {
        if(sum[Star]==0)     //未被记录则加入集合
        {
            Answer[Ansn++]=Star;
        }
        return 1;
    }
    else                      //不需要修复
        return 0;
}

int main()
{
    int n,i,j,a,b,c,ans;
    while(scanf("%d",&n)!=EOF)
    {
        Index=ans=Ansn=0;
        memset(pre,-1,sizeof(pre));
        memset(sum,0,sizeof(sum));
        memset(visit,0,sizeof(visit));
        for(i=1;i<n;i++)
        {
            scanf("%d%d%d",&a,&b,&c);
            Add_edge(a,b,c);
            Add_edge(b,a,c);
        }
        visit[1]=1;
        ans+=DFS(1,0);       //1结点开始深搜
        printf("%d\n",Ansn);
        for(i=0;i<Ansn;i++)
        {
            printf("%d",Answer[i]);
            if(i!=Ansn)
                printf(" ");
        }
        puts("");
    }
    return 0;
}

抱歉!评论已关闭.