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

传送门

题目描述

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

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

输入格式

第 1 1 1 行:两个整数 N , M N, M N,M。

第 2 2 2 到 M + 1 M+1 M+1 行:第 i + 1 i+1 i+1 行包含三个整数 A i , B i , L i A_i, B_i, L_i Ai,Bi,Li, A i A_i Ai 和 B i B_i Bi 表示道路 i i i 连接的田的编号, L i L_i Li 表示路长。

输出格式

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

输入输出样例 #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

说明/提示

【样例说明】

若使 3 3 3 和 4 4 4 之间的道路长加倍,最短路将由 1 → 3 → 4 → 5 1 \rightarrow 3 \rightarrow 4 \rightarrow 5 1→3→4→5 变为 1 → 3 → 5 1 \rightarrow 3 \rightarrow 5 1→3→5。

【数据规模和约定】

对于 30 % 30\% 30% 的数据, N ≤ 70 N \le 70 N≤70, M ≤ 1   500 M \le 1\,500 M≤1500。

对于 100 % 100\% 100% 的数据, 1 ≤ N ≤ 100 1 \le N \le 100 1≤N≤100, 1 ≤ M ≤ 5   000 1 \le M \le 5\,000 1≤M≤5000, 1 ≤ L i ≤ 1   000   000 1 \le L_i \le 1\,000\,000 1≤Li≤1000000。

思路

首先跑一遍最短路,看原最短需要走多少。

接着,枚举在每条边放稻草堆,跑最短路,记录最大增量。

注意:不能直接在 FJ 原来走的最短路中最长的边放,因为他还可以走其他边。

代码

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
int g[100001],n,m,dis[100001],to[100001],cnt,head[100001],p,Next[100001],w[100001],maxn=INT_MIN;
bool vis[100001];
queue<int>q;
void add(int u,int v,int l)
{
	++cnt;
	to[cnt]=v;	
	Next[cnt]=head[u];
	head[u]=cnt;	
	w[cnt]=l;
}
void spfa()
{
	for(int i=1;i<=n;i++)
		dis[i]=INT_MAX;
	memset(vis,0,sizeof vis);
	dis[1]=0;	
	q.push(1);
	vis[1]=1;
	while(!q.empty())
	{
		int u=q.front();
		q.pop();
		vis[u]=0;
		for(int i=head[u];i;i=Next[i])
		{
			int v=to[i];
			if(dis[v]>dis[u]+w[i])
			{
				dis[v]=dis[u]+w[i];
				if(!vis[v])
				{
					q.push(v);
					vis[v]=1;
				}			
			}	
		}
	}
}
int main()
{
	cin>>n>>m;
	for(int i=1;i<=m;i++)
	{
		int x,y,z;
		cin>>x>>y>>z;
		add(x,y,z);
		add(y,x,z);
	}
	spfa();
	int disn=dis[n];
	for(int i=1;i<=m;i++)
	{
		w[i*2-1]*=2;
		w[i*2]*=2;
		spfa();
		maxn=max(maxn,dis[n]-disn);
		w[i*2-1]/=2;
		w[i*2]/=2;
	}
	cout<<maxn;
	return 0;
}
相关推荐
雨季mo浅忆2 小时前
记录利用Cursor快速实现拖拽式问卷题型创建
算法
Yzzz-F2 小时前
2018-2019 ACM-ICPC, Asia Dhaka Regional ContestC[数论]
算法
Frostnova丶2 小时前
LeetCode 3474. 字典序最小的生成字符串
算法·leetcode·职场和发展
REDcker2 小时前
Nagle 算法与 TCP_NODELAY、TCP_CORK 详解
网络·tcp/ip·算法
β添砖java2 小时前
深度优先搜索DFS
算法·深度优先
小糯米6012 小时前
C++ 并查集
java·c++·算法
IronMurphy2 小时前
【算法三十四】39. 组合总和
算法·深度优先
重庆小透明2 小时前
力扣刷题【3】相交链表
算法·leetcode·链表
算法鑫探3 小时前
C语言实战:学生成绩统计与分析
c语言·数据结构·算法·新人首发