铲雪车:带权树最长路

铲雪车
时间限制: 1 s 空间限制: 512 MB
题目描述
大雪履盖了整个城市,市政府要求冬季服务部门尽快将一些街道(列在一份清单中)的积雪清除掉以恢复交通,整个城市由许多交叉路口和街道构成,当然任意两个交叉路口都是直接或间接连通的,清单给出了最少的街道,使得这些街道的积雪清除后任意两个交叉路口之间有且仅有一条通路,冬季服务部门只有一辆铲雪车及一名司机,这辆铲雪车的出发点位于某个交叉路口。无论街道上有没有积雪,铲雪车每前进一米都要消耗一升燃料,冬季服务部门要求司机在铲除清单上的所有街道的积雪的前提下,要求消耗燃料最少,积雪铲完后车可以停在任意的交叉路口。大雪履盖了整个城市,市政府要求冬季服务部门尽快将一些街道(列在一份清单中)的积雪清除掉以恢复交通,整个城市由许多交叉路口和街道构成,当然任意两个交叉路口都是直接或间接连通的,清单给出了最少的街道,使得这些街道的积雪清除后任意两个交叉路口之间有且仅有一条通路,冬季服务部门只有一辆铲雪车及一名司机,这辆铲雪车的出发点位于某个交叉路口。无论街道上有没有积雪,铲雪车每前进一米都要消耗一升燃料,冬季服务部门要求司机在铲除清单上的所有街道的积雪的前提下,要求消耗燃料最少,积雪铲完后车可以停在任意的交叉路口。
输入文件的第一行包含两个整数 N 和 S,1≤N≤100000,1≤S≤N。N 为交叉路口的总数;S 为铲
雪车出发的路口序号。路口的标号为 1~N。
接下来的 N-1 行为清单上的街道,每一行包含三个用空格隔开的整数 A、B、C,表示一条从交叉
路口 A 到交叉路口 B 的街道,C 为该街道的长度,单位为米,1≤C≤1000。
输出
输出文件仅一行包含一个整数表示清除所有积雪所需的最少的燃料数量。
样例输入
5 1
1 2 1
2 3 1
3 5 1
3 4 1
样例输出
5
样例输入
10 2
1 2 1
2 3 1
3 4 5
3 5 1
2 7 1
7 6 1
7 8 10
8 9 1
8 10 1
样例输出
32
分析:因任意两个交叉路口之间有且仅有一条通路,本题即遍历完整棵树,对于每一条边,最多遍历两次,最少遍历一次,我们要让最长通路遍历一次,其余边遍历两次。即将边之和乘二,减去最长通路的长度。
本问题变成寻找带权树中两节点最长路径问题。
算法分析:每个节点都保存相邻节点的标识与距离,从头节点开始遍历整个树,将其子节点压入栈中,不断pop与push,不断计算节点到达头节点的距离,并与最大距离maxLength比较代替,遍历完整棵树后便得到最大距离。压栈需要n次,退栈需要n次,时间复杂度为n。

#include 
#include 
#include 
#include 
using namespace std;
struct lineNode
{
    int nextTo;
    long int length;
};
struct treeNode
{
    long int length;
    int flag;
    int statu;
    vector<lineNode>access;
};
int main()
{
    int N,s;
    cin>>N>>s;
    int A,B,C;
    long long lengthAll=0;
    lineNode line1,line2;
    vector<treeNode>tree(N);
    int maxLength=0;
    vector<treeNode>visit;
    for(int count1=0;count1<N-1;count1++)
    {
        scanf("%d %d %d",&A,&B,&C);
        line1.length=C;
        line2.length=C;
        line1.nextTo=A-1;
        line2.nextTo=B-1;
        tree.at(A-1).access.push_back(line2);
        tree.at(A-1).flag=A-1;
        tree.at(A-1).statu=0;
        tree.at(B-1).access.push_back(line1);
        tree.at(B-1).flag=B-1;
        tree.at(B-1).statu=0;
        lengthAll+=C;
    }
    visit.push_back(tree[s-1]);
    treeNode thisTree,lastTree;
    long int lastLength;
    vector<lineNode>::iterator i1;
    tree[s-1].length=0;
    tree[s-1].statu=1;
    thisTree=visit.back();
    visit.pop_back();
    for(i1=thisTree.access.begin();i1!=thisTree.access.end();i1++)
            visit.push_back(tree[(*i1).nextTo]);
    while(visit.size())
    {
        thisTree=visit.back();
        visit.pop_back();
        tree[thisTree.flag].statu=1;
        for(i1=thisTree.access.begin();i1!=thisTree.access.end();i1++)
        {
            if(tree[(*i1).nextTo].statu==0)
            {

                visit.push_back(tree[(*i1).nextTo]);
            }
            else if(tree[(*i1).nextTo].statu==1)
            {
                lastTree=tree[(*i1).nextTo];
                lastLength=(*i1).length;
            }
        }
        thisTree.length=lastTree.length+lastLength;
        if(thisTree.length>maxLength)
            maxLength=thisTree.length;
        tree[thisTree.flag].length=thisTree.length;
    }
    lengthAll*=2;
    lengthAll-=maxLength;
    cout<<lengthAll;
}

你可能感兴趣的:(cpp)