COGS 2095. 不平凡的引线

2095. 不平凡的引线

★☆   输入文件:firelead.in   输出文件:firelead.out   简单对比
时间限制:1 s   内存限制:256 MB

【题目描述】

这里说的引线是炮仗的引线,它可以匀速的燃烧。熊孩子经常会把引线抽出,点引线玩。但是有些熊孩子看到这些并不满足,于是他们把引线的形状摆成一棵树。同时点燃所有的叶子结点,多少单位时间后引线才能燃烧完?可以认为每个单位时间会燃烧一个单位长度的引线。

如上图共有3条引线,其中(1,2)引线的单位长度为2,(2,3)引线单位长度为1,(2,4)引线单位长度为1。现在同时点燃所有叶子结点(叶子结点 定义为只与一条边相邻的结点,如上图中的叶子结点为1,3,4)。1个单位时间以后,(2,3),(2,4)被完全烧完,(1,2)仅剩一半。这时剩下的 半段(1,2)两头均被引燃,所以再过0.5个单位时间后,(1,2)被完全烧完。共需1.5个单位时间。

【输入格式】


第一行一个整数m,表示共有m条引线。

接下来m行,每行三个整数u,v,len表示有一条引线两端分别是u和v,其长度为len


【输出格式】

一个浮点数,表示需要多少单位时间引线会燃烧完,保留一位小数。

【样例输入】

3
1 2 2
2 3 1
2 4 1

【样例输出】

1.5

【提示】


数据范围与约定:

对于30%的数据:m+1 <= 100,保证引线长度均为1

对于60%的数据:m+1 <= 1000,保证引线长度均为1

对于100%的数据:m+1 <= 100000,保证输入的引线一定可以构成一棵树,引线的长度len满足1 <= len <= 10000。

m条边的节点标号范围从1到m+1

 

 

题解:

  这个题目真的妙不可言,考试的时候只想到模拟。

  好了,这个题目求每条边被烧到的时间非常困难,直接求是n平方的,所以我们考虑先求出每个点被烧到的时间,显然是当前节点到所有节点的最短路,这个取min,这个东西可以一次spfa求出来,只要把所有的点事先加如队列之中求出来的就是i这个节点到每个叶子节点的最短路(取min,并且对于图也一样)。

  然后求出来点的,就可以推公式求边的了,显然答案就是所有条边被烧完的时间取max,然后考虑怎么推,当dis[to]=dis[now]+quan时(now和to是边上的两个节点,权值是边权),时间=dis[now]+quan=(dis[now]+dis[to]+quan)/2;当dis[to]<dis[now]+quan时(令dis[to]>dis[now]),时间=dis[now]+dis[to]-dis[now]+(quan-(dis[to]-dis[now]))/2=(dis[now]+dis[to]+quan)/2。(因为我们是用多源最短路求的dis,所以不存在dis[now]>dis[to]+quan)把公式带进去就可以了。

 

代码:

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <iostream>
#include <queue>
#define MAXN 200100
using namespace std;
struct edge{
    int first;
    int next;
    int to;
    int quan;
}a[MAXN*2];
int in[MAXN];
double dis[MAXN];
bool have[MAXN];
int m,num=0,n;
queue<int> q;

void addedge(int from,int to,int quan){
    a[++num].to=to;
    a[num].quan=quan;
    a[num].next=a[from].first;
    a[from].first=num;
}

void spfa(){
    while(!q.empty()) q.pop();
    memset(dis,127,sizeof(dis));
    for(int i=1;i<=n;i++){
        if(in[i]==1){
            dis[i]=0,q.push(i),have[i]=1;
        }
    }
    while(!q.empty()){
        int now=q.front();
        q.pop();have[now]=0;
        for(int i=a[now].first;i;i=a[i].next){
            int to=a[i].to,quan=a[i].quan;
            if(dis[to]>dis[now]+quan){
                dis[to]=dis[now]+quan;
                if(!have[to]){
                    have[to]=1;
                    q.push(to);
                }
            }
        }
    }
}

int main()
{
    scanf("%d",&m);n=m+1;
    for(int i=1;i<=m;i++){
        int x,y,z;scanf("%d%d%d",&x,&y,&z);
        addedge(x,y,z);
        addedge(y,x,z);
        in[x]++;in[y]++;
    }
    spfa();
    double ans=0;
    for(int now=1;now<=n;now++){
        for(int i=a[now].first;i;i=a[i].next){
            int to=a[i].to,quan=a[i].quan;
            double x=(dis[now]+dis[to]+quan)/2.0;
            ans=max(ans,x);
        }
    }
    printf("%0.1f",ans);
    return 0;
}

 

posted @ 2017-08-23 16:33  人间失格—太宰治  阅读(220)  评论(0编辑  收藏  举报