HDU 3848 DFS 树形DP

来源:互联网 发布:无限量流量软件 编辑:程序博客网 时间:2024/05/20 14:18

            给你一棵树,找出两个叶子之间的最短距离。

            第一种是个纯dfs+稍微的剪枝,从每一个叶子出发,dfs直到找到一个新的叶子,更新最短距离。781ms

#include<cstdio>#include<cstring>#include<iostream>#include<vector>#include<queue>#define MAXN 10001#define INF  2147483647using namespace std;int n;vector<int>g[MAXN],w[MAXN];int angel[MAXN];int maxx;bool vis[MAXN];void dfs(int ori,int cur,int dis){    if(dis>=maxx)   return  ;    vis[cur]=true;    if(angel[cur]==1&&cur!=ori)    {        maxx=min(maxx,dis);        return ;    }    for(int i=0; i<(int)g[cur].size(); i++)    {        int t=g[cur][i];        if(!vis[t]&&w[cur][i]+dis<maxx)            dfs(ori,t,w[cur][i]+dis);    }}int  main(){//    freopen("in.txt","r",stdin);    while(scanf("%d",&n)!=EOF&&n)    {        for(int i=0; i<=n; i++)            g[i].clear(),w[i].clear(),angel[i]=0;        maxx=INF;        for(int i=0; i<n-1; i++)        {            int a,b,c;           scanf("%d%d%d",&a,&b,&c);            angel[a]++,angel[b]++;            g[a].push_back(b),w[a].push_back(c);            g[b].push_back(a),w[b].push_back(c);        }        for(int i=1; i<=n; i++)            if(angel[i]==1)            {                memset(vis,false,sizeof(vis));                dfs(i,i,0);            }        printf("%d\n",maxx);    }    return 0;}
              第二种是新接触的树形dp,从任意一个节点出发,dfs回溯,dp[cur][0]表示cur节点到叶子的最短距离,dp[cur][1]表示cur节点到叶子的次短距离。注意dp数组的初始化,(每一个叶子到叶子的最短距离是0)。PS.树形dp,它的原理和名字很像。dp[cur][0]=min{dp[cur][0],dp[u][0]+dis(u,cur)],因为父节点cur的dp值通过子节点来得出,所以通过回溯递归求解每一个节点的dp[][].

#include<cstdio>#include<cstring>#include<iostream>#include<vector>#define MAXN 10010#define INF 20000000using namespace std;vector<int>g[MAXN],w[MAXN];int n,dp[MAXN][2],degree[MAXN];bool  vis[MAXN];int maxx;void dfs(int cur){    vis[cur]=true;    for(int i=0; i<(int)g[cur].size(); i++)    {        int t=g[cur][i];        if(!vis[t])        {            dfs(t);            if(w[cur][i]+dp[t][0]<dp[cur][0])            {                dp[cur][1]=dp[cur][0];                dp[cur][0]=w[cur][i]+dp[t][0];            }            else if(w[cur][i]+dp[t][0]<dp[cur][1])                dp[cur][1]=w[cur][i]+dp[t][0];//            printf("cur:%d %d %d\n",cur,dp[cur][0],dp[cur][1]);        }    }    maxx=min(maxx,dp[cur][0]+dp[cur][1]);}int main(){    freopen("in.txt","r",stdin);    while(scanf("%d",&n)!=EOF&&n)    {        for(int i=0; i<=n; i++)            g[i].clear(),w[i].clear(),degree[i]=0;        for(int i=1; i<n; i++)        {            int a,b,c;            scanf("%d%d%d",&a,&b,&c);            degree[a]++,degree[b]++;            g[a].push_back(b),g[b].push_back(a);            w[a].push_back(c),w[b].push_back(c);        }        for(int i=1; i<=n; i++)        {            dp[i][0]=dp[i][1]=INF;            if(degree[i]==1)                dp[i][0]=0;        }        memset(vis,false,sizeof(vis));        maxx=INF;        dfs(1);        printf("%d\n",maxx);    }    return 0;}

原创粉丝点击