洛谷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
", time2 - time1);
return 0;
}