FZU 2195 思维

很无聊的背景故事...求最短的时间原来就是省去了检查员最后上山的时间...还让不让人回家了...

感觉这是个最短路 

思想是求出来dis 然后求里面最大的那条边 用总长减去最长边 就是答案

写了一个小时...dij用的还是有些不熟练 还出现了初始化dis[0]==1这种卖萌的行为

最后千辛万苦debug结束后发现...超时了...

我还是要放上来纪念这段思想...算法是没错的...虽然很长也很耗时间...但这是我第一次用vector写dij...还是独立...

#define INF 1000500000
int dis[100000];
bool book[100000];
struct node
{
    int b;
    int w;
};
int n;
int main(){
while(~scanf("%d",&n))
{
    int zong=0;
    for(int i=1;i<=n;i++)
        {
            dis[i]=INF;

        }
    memset(book,true,sizeof(book));
    dis[1]=0;
    book[1]=false;
    vector<node >a[n+1];
    int q,e,r;
    for(int i=1;i<=n-1;i++)
    {
        scanf("%d%d%d",&q,&e,&r);
        node t;
        t.b=e;
        t.w=r;
        a[q].push_back(t);
        t.b=q;
        a[e].push_back(t);
        zong+=r;
    }
    for(int i=1;i<=n-1;i++)
    {
        int e=a[1].size();
        int minn=INF;
        int wh=1;
        for(int k=1;k<=n;k++)
        {
            if(dis[k]<minn&&book[k]==true)
            {
                minn=dis[k];
                wh=k;
            }
        }
        book[wh]=false;

        int ee=a[wh].size();

        for(int k=0;k<ee;k++)
        {

            if(dis[a[wh][k].b]>dis[wh]+a[wh][k].w&&book[a[wh][k].b]==true)
            {
                dis[a[wh][k].b]=dis[wh]+a[wh][k].w;

            }
        }
    }
    int ans=0;
    for(int i=2;i<=n;i++)
    {
        if(dis[i]>ans&&dis[i]<1000005000)
        {
            ans=dis[i];
        }
    }
    for(int i=1;i<=n;i++)
    {
        printf("%d ",dis[i]);
    }
    puts("");

    printf("%d
",zong-ans);
}
}

然后接受了学妹神奇的思想 : x 是y的父节点。dy=dx+1

很简单的就想到排序后直接算了

由于排序方法是这样的 那么当我们算到3->5这条边的时候 3一定已经作为目标被行为过了 所以一开始对dis数组只需要初始化dis[1]为0即可 肯定不会出现3还没有dis值得情况

然而还是wa了.. 有些莫名

struct node
{
    int a,b,w;
};
int dis[100050];
int cmp(node a,node b)
{
    if(a.a==b.a)
        return a.b<b.b;
    else return a.a<b.a;
}
int main(){
int n;
while(~scanf("%d",&n))
{
    int zong=0;
    dis[1]=0;
    node q[n-1];
    for(int i=0;i<n-1;i++)
    {
        scanf("%d%d%d",&q[i].a,&q[i].b,&q[i].w);
        zong+=q[i].w;
    }
    sort(q,q+n-1,cmp);
    int maxx=0;
    for(int i=0;i<n-1;i++)
    {
        dis[q[i].b]=dis[q[i].a]+q[i].w;
    }
    for(int i=1;i<=n;i++)
    {
        if(dis[i]>maxx)
            maxx=dis[i];
    }
    zong-=maxx;
    printf("%d
",zong);

}
}

后来我就去看百度了..忽然发现了fa数组的用处..

于是循环找父节点相加就写出来了...

time数组代表的是当前节点的时间 因为它是一棵树所以当前节点时间唯一

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<map>
#include<math.h>
#include<queue>
using namespace std;
int fa[100050];
int time[100050];
int find(int x)
{
    int sum=0;
    while(x)
    {
        sum+=time[x];
        x=fa[x];
    }
    return sum;
}
int main()
{
    int n;
    while(~scanf("%d",&n))
    {
        int zong=0;
        memset(fa,0,sizeof(fa));
        int q,e,w;
        for(int i=1;i<=n-1;i++)
        {
            scanf("%d%d%d",&q,&e,&w);
            zong+=w;
            time[e]=w;
            fa[e]=q;
        }
        int maxx=0;
        for(int i=2;i<=n;i++)
        {
            int sum=find(i);
            if(sum>maxx)
                maxx=sum;
        }
        zong-=maxx;
        printf("%d
",zong);
    }

}

  

将近两个小时过去了...

原文地址:https://www.cnblogs.com/rayrayrainrain/p/5248486.html