poj 2631 Roads in the North BFS树状DP

    xiaoxiao2025-01-10  6

    传送门:poj 2631 Roads in the North

    题目大意

    输入边的两个顶点和权值,输出任意两个顶点的最远距离;

    解题思路

    这是一个裸的求树的直径的题目。 先说用BFS的方式,第一个BFS随便找一个顶点进行松弛,找到最远的一条路径并且记录下来那个顶点,因为这个距离肯定是包含在了最后的最长路径里面,所以在对刚才找到的那个节点进行一次BFS找到就是树的直径。

    AC代码

    #include<cstdio> #include<cstring> #include<queue> using namespace std; const int MAXN = 10000 + 5000; const int INF = 0x3f3f3f3f; int head[MAXN],e; long long dis[MAXN],ans; bool vis[MAXN]; struct Edge{ int v,nxt,w; }E[MAXN<<1]; void init() { e=0; memset(head,-1,sizeof head); } void add(int u,int v,int w) { E[e].v=v; E[e].w=w; E[e].nxt = head[u]; head[u]=e++; } int BFS(int s) { int se = s; long long MAX = 0; ans = 0; queue<int>Q; Q.push(s); memset(vis,false,sizeof vis); vis[s] = true; dis[s] = 0; while(!Q.empty()) { int u = Q.front();Q.pop(); for(int i=head[u];~i;i=E[i].nxt){ int v = E[i].v; if(vis[v])continue; vis[v] = true; dis[v] = dis[u]+E[i].w; if(dis[v]>MAX){ se = v; MAX = dis[v]; ans = dis[v]; } Q.push(v); } } return se; } int main() { int u,v,w; // freopen("in.txt","r",stdin); init(); while(scanf("%d%d%d",&u,&v,&w) != EOF){ add(u,v,w); add(v,u,w); } BFS(BFS(1)); printf("%lld\n",ans); return 0; }

    还有一种方法就是使用树状DP。 dis[i][0]表示第i个节点的子树中最长的距离; dis[i][1]表示第i个节点的子树中次长的距离; 如下图: 首先先要递归到叶子节点,比如说先递归到了I节点: dp[I][0] = 7; dp[I][1] = 0; 然后递归到了D节点 dp[D][0] = 13; dp[D][1] = 1; 最后一直到A节点,他的子树的最大长度和子树的次大长度就是树的直径! 然后就是维护每个节点子树的最长距离和次长距离就可以了!

    AC代码

    #include<cstdio> #include<cstring> const int MAXN = 1e5+50; int head[MAXN],e,dis[MAXN][3]; bool vis[MAXN]; struct Edge{ int u,v,nxt,w; }E[MAXN<<1]; void add(int u,int v,int w) { E[e].v = v; E[e].w = w; E[e].nxt=head[u]; head[u] = e++; } void DFS(int u) { vis[u] = true; //printf("[%d]\n",u); for(int i=head[u];~i;i=E[i].nxt){ int v = E[i].v; if(vis[v])continue; DFS(v); if(dis[u][0]<dis[v][0]+E[i].w){ dis[u][1] = dis[u][0]; dis[u][0] = dis[v][0]+E[i].w; } else if(dis[u][1]<dis[v][0]+E[i].w) dis[u][1] = dis[v][0]+E[i].w; } } int main() { e=0;memset(vis,false,sizeof vis); memset(head,-1,sizeof head); memset(dis,0,sizeof dis); int u,v,w,n=0,ans=0; //freopen("in.txt","r",stdin); while(~scanf("%d%d%d",&u,&v,&w)){ add(u,v,w);add(v,u,w); n++; } DFS(1); for(int i=1;i<=n;i++) if(ans<dis[i][0]+dis[i][1]) ans = dis[i][0] + dis[i][1]; printf("%d\n",ans); return 0; }
    转载请注明原文地址: https://ju.6miu.com/read-1295346.html
    最新回复(0)