洛谷P2176 [USACO14FEB]路障Roadblock

洛谷P2176 [USACO14FEB]路障Roadblock

题目描述

每天早晨,FJ从家中穿过农场走到牛棚。农场由 \(N\) 块农田组成,农田通过 \(M\) 条双向道路连接,每条路有一定长度。FJ 的房子在 1 号田,牛棚在 \(N\) 号田。没有两块田被多条道路连接,以适当的路径顺序总是能在农场任意一对田间行走。当FJ从一块田走到另一块时,总是以总路长最短的道路顺序来走。

FJ 的牛呢,总是不安好心,决定干扰他每天早晨的计划。它们在 \(M\) 条路的某一条上安放一叠稻草堆,使这条路的长度加倍。牛希望选择一条路干扰使得FJ 从家到牛棚的路长增加最多。它们请你设计并告诉它们最大增量是多少。

输入输出格式

输入格式:

\(1\) 行:两个整数 \(N\), \(M\)
\(2\)\(M+1\) 行:第 \(i+1\) 行包含三个整数 \(A_i\), \(B_i\), \(L_i\)\(A_i\)\(B_i\) 表示道路 \(i\) 连接的田的编号,\(L_i\) 表示路长。

输出格式:

\(1\) 行:一个整数,表示通过使某条路加倍而得到的最大增量。

思路

为了得到更大的最短距离,就一定要改变当前最短路径上的边
那么就用一个很朴素的方法,枚举当前最短路上的每一条边,增大这条边的长度,然后再求最短路
最后取个最大值就可以求出答案

CODE

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
#define MAXN 210
#define MAXM 20010
struct Node{
	int u,v,w;
	Node(){}
	Node(int u,int v,int w):u(u),v(v),w(w){}
}p[MAXM];
struct R{
	int val,id;
	R(){}
	R(int val,int id):val(val),id(id){}
	bool operator < (const R &a) const{
		return val>a.val;
	}
}tmp;
int head[MAXN],Next[MAXM],dis[MAXN],pre[MAXN],li[MAXN];
bool vis[MAXN];
int i,j,k,m,n,u,v,w,tot,cnt,ans,dist;
priority_queue<R> mque;
void addNode(int u,int v,int w){
	p[++tot]=Node(u,v,w);
	Next[tot]=head[u],head[u]=tot;
	p[++tot]=Node(v,u,w);
	Next[tot]=head[v],head[v]=tot;
}
bool relax(int u,int v,int w){
	if(dis[u]+w<dis[v]){
		dis[v]=dis[u]+w;
		return true;
	}
	return false;
}
int dijkstra(int src,int goal){
	while(!mque.empty()) mque.pop();
	for(int i=1;i<=n;i++) dis[i]=1000000000;
	memset(vis,0,sizeof(vis));
	dis[src]=0;
	pre[src]=-1;
	mque.push(R(0,src));
	while(!mque.empty()){
		tmp=mque.top(); mque.pop();
		if(vis[tmp.id]) continue;
		vis[tmp.id]=true;
		for(int i=head[tmp.id];i+1;i=Next[i]){
			if(relax(p[i].u,p[i].v,p[i].w)){
				pre[p[i].v]=i;
				mque.push(R(dis[p[i].v],p[i].v));
			}
		}
	}
	return dis[goal];
}
void dfs(int src){
	if(src==-1) return;
	dfs(pre[p[src].u]);
	li[++cnt]=src;
}
int main(){
	memset(head,-1,sizeof(head));
	tot=-1;
	scanf("%d%d",&n,&m);
	for(i=1;i<=m;i++){
		scanf("%d%d%d",&u,&v,&w);
		addNode(u,v,w);
	}
	dist=dijkstra(1,n);
	dfs(pre[n]);
	ans=0;
	for(i=1;i<=cnt;i++){
		p[li[i]].w*=2;
		p[li[i]^1].w*=2;
		ans=max(ans,dijkstra(1,n));
		p[li[i]].w/=2;
		p[li[i]^1].w/=2;
	}
	printf("%d\n",ans-dist);
	return 0;
}
posted @ 2018-11-30 23:38  EternalBlue  阅读(188)  评论(0)    收藏  举报