[Usaco2014 Feb] Roadblock

有一个无向图,共N个节点,编号1至N,共M条边。FJ在节点1,它想到达节点N。FJ总是会选择最短路径到达节点N

。作为捣蛋的奶牛Bessie,它想尽量延迟FJ到达节点N的时间,于是Bessie决定从M条边之中选择某一条边,使得改
边的长度变成原来的两倍,由于智商的问题,Bessie不知道选择加倍哪条边的长度才能使得FJ到达N号节点的时间
最迟。注意:不管Bessie选择加倍哪条边的长度,FJ总是会从1号节点开始走最短路径到达N号点。

Input

第一行,两个整数N和M. 1 <=N<=250, 1<=M<=250000。

接下来有M行,每行三个整数:A,B,L,表示节点A和节点B之间有一条长度为L的无向边。1<=L<=1000000。

Output

一个整数。Bessie选择了加倍某一条边的长度后,奶牛FJ从节点1到达节点N的最短路径是多少。但是输出的格式
有变化,假设Bessie没有加倍某一条边的长度之前,FJ从1号节点到达N号节点的最短路径是X;在Bessie加倍某一
条边的长度之后,FJ从1号节点到达N号节点的最短路径是Y,那么你输出的结果是Y-X。

Sample Input

5 7

2 1 5

1 3 1

扫描二维码关注公众号,回复: 7700468 查看本文章

3 2 8

3 5 7

3 4 3

2 4 7

4 5 2

INPUT DETAILS: There are 5 fields and 7 pathways. Currently, the shortest path from the house (field 1) to the barn (field 5) is 1-3-4-5 of total length 1+3+2=6.
Sample Output

2

(把节点3到节点4的边从原来的长度3变成长度6)

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<map>
#include<queue>
#include<set>
#define ll long long
#define llu unsigned ll
using namespace std;
const int mod=1000000007;
const int maxn=50100;
const int maxx=300;
const int inf=0x3f3f3f3f;
int head[maxx],edge[maxn],ver[maxn],nt[maxn];
int d[maxx];
int ha[maxx];
int pre[maxx];
int tot=1,n,m;
bool flag=false;

void add(int x,int y,int z)
{
    ver[++tot]=y,edge[tot]=z;
    nt[tot]=head[x],head[x]=tot;
}

int Dij(void)
{
    memset(d,0x3f,sizeof(d));
    memset(ha,0,sizeof(ha));
    d[1]=0;
    priority_queue<pair<int,int> >q;//默认为大根堆 
    q.push(make_pair(0,1));
    while(q.size())
    {
        int x=q.top().second;
        q.pop();
        if(ha[x]) continue;
        ha[x]=true;
        for(int i=head[x];i;i=nt[i])
        {
            int y=ver[i],z=edge[i];
            if(d[y]>d[x]+z)
            {
                d[y]=d[x]+z;
                if(!flag) //最开始算最短路时,记上y点在最短路上的父亲边是哪条边 
                    pre[y]=i;
                q.push(make_pair(-d[y],y));
            }
        }
    }
    return d[n];
}


int main(void)
{
    scanf("%d%d",&n,&m);
    int x,y,z;
    for(int i=1;i<=m;i++)
    {
        scanf("%d%d%d",&x,&y,&z);
        add(x,y,z);
        add(y,x,z);
    }
    int cnt=Dij();
    flag=true;
    int _max=0;
    for(int i=2;i<=n;i++)//枚举点 
    {
        int k=pre[i];
        if (k==0)//如果不在最短路径上就不管了 
		 continue;
        edge[k]=edge[k]*2,edge[k^1]=edge[k^1]*2;
        _max=max(_max,Dij());
        edge[k]=edge[k]/2,edge[k^1]=edge[k^1]/2;
    }
    printf("%d\n",_max-cnt);
    return 0;
}

  

猜你喜欢

转载自www.cnblogs.com/cutemush/p/11772799.html