HDU 3848 DFS 樹形DP

            給你一棵樹,找出兩個葉子之間的最短距離。

            第一種是個純dfs+稍微的剪枝,從每一個葉子出發,dfs直到找到一個新的葉子,更新最短距離。781ms

#include<cstdio>
#include<cstring>
#include<iostream>
#include<vector>
#include<queue>
#define MAXN 10001
#define INF  2147483647
using 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 20000000
using 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;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章