[USACO2011Dec] Roadblock

    xiaoxiao2021-12-14  23

    题目描述

    N (1 <= N <= 100)个点,M (1 <= M <= 10,000)条双向通行的边,每条边有一个长度值。两点之间若有边,则只有一条边。任意点对之间都有通路。FJ总是行走长度最短的路径。 现在求:若可任意选择一条边,把它的长度*2,则从编号1的点到编号N的点之间的最短距离,最长可以增加多少距离。

    输入格式

    第一行: 两个整数 N,M. 行 2..1+M:行 j+1表示第 j条双向边情况,aj bj Lj (端点编号及边长 1<=lj<=1,000,000,整数).

    输出格式

    1行:最短路最大增加长度

    样例输入

    5 7 2 1 5 1 3 1 3 2 8 3 5 7 3 4 3 2 4 7 4 5 2

    样例输出

    2

    题目分析

    刚刚写完最短路径上边权减半问题就看到这题,可惜不能直接套模板,因为这题求的是最大。 既然如此就随便暴力搞搞吧。 跑一次Dijkstra求出最短路,然后枚举所有最短路上的边,将边权*2再跑一次Dijkstra。 我的代码中有一个小技巧:在第一次Dijkstra时就保存路径path以及在路径上的点和前驱结点相连的边的邻接表编号,因此可以方便地修改边权。

    源代码

    #include<algorithm> #include<iostream> #include<iomanip> #include<cstring> #include<cstdlib> #include<vector> #include<cstdio> #include<cmath> #include<queue> using namespace std; inline const int Get_Int() { int num=0,bj=1; char x=getchar(); while(x<'0'||x>'9') { if(x=='-')bj=-1; x=getchar(); } while(x>='0'&&x<='9') { num=num*10+x-'0'; x=getchar(); } return num*bj; } const int maxn=505; //数组范围 struct Edge { //前向星 int from,to,dist; } E[50005]; struct HeapNode { int d,u; //u为当前结点 bool operator < (HeapNode a) const { return d>a.d; } }; struct Dijkstra { int n,m; vector<Edge> edges; //邻接表 vector<int> G[maxn]; //记录每个结点可以到达的结点 bool vst[maxn]; int dist[maxn],path[maxn],pathe[maxn]; //使用path记录最短路 void init(int n) { this->n=n; for(int i=1; i<=n; i++)G[i].clear(); edges.clear(); } void AddEdge(int from,int to,int dist) { edges.push_back((Edge) { from,to,dist }); m=edges.size(); G[from].push_back(m-1); } void main(int s) { //核心算法 priority_queue<HeapNode> Q; for(int i=1; i<=n; i++)dist[i]=0x7fffffff/2; dist[s]=0; path[s]=s; memset(vst,0,sizeof(vst)); Q.push((HeapNode) { 0,s }); while(!Q.empty()) { HeapNode Now=Q.top(); Q.pop(); if(vst[Now.u])continue; vst[Now.u]=1; for(int i=0; i<G[Now.u].size(); i++) { Edge& e=edges[G[Now.u][i]]; //边的信息 int Next=e.to; if(dist[Next]>dist[Now.u]+e.dist) { dist[Next]=dist[Now.u]+e.dist; path[Next]=Now.u; pathe[Next]=G[Now.u][i]; Q.push((HeapNode) { dist[Next],Next }); } } } } void Output(int x) { if(path[x]==x) { cout<<x<<" "; return; } Output(path[x]); cout<<x<<" "; } } ; Dijkstra dij; int n,m,ans=-0x7fffffff/2,Ans,path[maxn],pathe[maxn]; int main() { n=Get_Int(); m=Get_Int(); dij.init(n); for(int i=1; i<=m; i++) { int x=Get_Int(),y=Get_Int(),v=Get_Int(); dij.AddEdge(x,y,v); dij.AddEdge(y,x,v); } dij.main(1); Ans=dij.dist[n]; memcpy(path,dij.path,sizeof(dij.path)); memcpy(pathe,dij.pathe,sizeof(dij.pathe)); for(int i=n; i!=1; i=path[i]) { Edge& e=dij.edges[pathe[i]]; e.dist*=2; dij.main(1); ans=max(ans,dij.dist[n]-Ans); e.dist/=2; } printf("%d\n",ans); return 0; }

    转载请注明原文地址: https://ju.6miu.com/read-970479.html

    最新回复(0)