洛谷P2176 [USACO11DEC]RoadBlock S / [USACO14FEB]Roadblock G/S

洛谷P2176 [USACO11DEC]RoadBlock S / [USACO14FEB]Roadblock G/S

[传送门][https://www.luogu.com.cn/problem/P2176]

题目描述

每天早晨,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 行:一个整数,表示通过使某条路加倍而得到的最大增量。

输入输出样例

输入 #1复制

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

输出 #1复制

2

题解

数据很水, (我一开始居然写了个分层图, 如此智障不愧是我)

枚举要乘二的边, 每次跑一遍最长路, 其实毫无技术含量

#include<cstdio>
#include<algorithm>
#include<queue>
#include<cstring>
using namespace std;
const int maxn = 255, maxe = 250005;
int len, head[maxn], n, m, dis[maxn], vis[maxn];
struct edge{
	int next, to, t;
}e[maxn*maxe];
void insert(int x, int y, int t){
	e[++len].to = y;
	e[len].t = t;
 	e[len].next = head[x];
	head[x] = len;
}
void spfa(int s){
	memset(dis, 0x3f, sizeof(dis));
	memset(vis, 0, sizeof(vis));
	queue<int> que;
	que.push(s);
	vis[s] = 1;
	dis[s] = 0;
	while(!que.empty()){
		int u = que.front();
		que.pop();
		vis[u] = 0;
		for(int i=head[u]; i; i=e[i].next){
			int v = e[i].to;
			if(dis[v] > dis[u] + e[i].t){
				dis[v] = dis[u] + e[i].t;
				if(!vis[v]){
					que.push(v);
					vis[v] = 1;
				}
			}
		}
	}
}
int main(){
    scanf("%d%d", &n, &m);
	for(int i=1; i<=m; i++){
		int a, b, t;scanf("%d%d%d", &a, &b, &t);
		insert(a, b, t); insert(b, a, t);
	}
	spfa(1); 
	int time1 = dis[n];
	int time2 = 0;
	for(int i=1; i<=2*m; i+=2){
		e[i].t*=2; e[i+1].t*=2;
		spfa(1);
		if(dis[n] > time2) time2 = dis[n];
		e[i].t/=2; e[i+1].t/=2; 
	}
	printf("%d\n", time2 - time1);
    return 0;
}
posted @ 2020-05-06 19:54  poozhai  阅读(134)  评论(0编辑  收藏  举报