题目链接:HDU-3986
主要思路:
要使其删除一条边后最短路径最长,就必须删掉原最短路径上的边(删其它边对答案没有贡献)。故在求最短路时记录走过的路径,一条条枚举删去那条即可。
AC代码:
#include<cstdio>
#include<queue>
#include<vector>
#include<cstring>
#define M 100005
#define N 1005
#define INF 1000000000
using namespace std;
struct E {
int to,nx,d,from;
} edge[M];
int tot,head[N];
void Addedge(int a,int b,int d) {
edge[++tot].to=b;
edge[tot].nx=head[a];
edge[tot].from=a;
edge[tot].d=d;
head[a]=tot;
}
struct node {
int d,id;
node(int d,int id):d(d),id(id) {}
bool operator<(const node &x)const {
return d>x.d;
}
};
priority_queue<node> Q;
vector<int>E;
int dis[N],pre[M];
bool done[M];
int dijkstra(int notgo,int n) {//十分正常的dijkstra
for(int i=1; i<=n; i++)dis[i]=INF;
dis[1]=0;
memset(done,0,sizeof(done));
Q.push(node(dis[1],1));
while(!Q.empty()) {
int now=Q.top().id;
Q.pop();
if(done[now])continue;
done[now]=1;
for(int i=head[now]; i; i=edge[i].nx) {
if((i+1)/2!=(notgo+1)/2) {//去掉的是双向边
int nxt=edge[i].to;
if(dis[nxt]>dis[now]+edge[i].d) {
dis[nxt]=dis[now]+edge[i].d;
pre[nxt]=i;//记录到达nxt的最短路的边是那条
Q.push(node(dis[nxt],nxt));
}
}
}
}
return dis[n];
}
int main() {
int T;
scanf("%d",&T);
while(T--) {
tot=0;
memset(head,0,sizeof(head));
int n,m;
scanf("%d%d",&n,&m);
while(m--) {
int a,b,d;
scanf("%d%d%d",&a,&b,&d);
Addedge(a,b,d);
Addedge(b,a,d);
}
int D=dijkstra(-1,n);//-1代表不去掉任何边
if(D==INF) {//若无法到达
puts("-1");
continue;
}
E.clear();
int ed=n,ans=0;
while(ed) {
int ED=pre[ed];
E.push_back(ED);
ed=edge[ED].from;
}
for(int i=0; i<E.size(); i++)ans=max(ans,dijkstra(E[i],n));
if(ans!=INF)printf("%d\n",ans);
else puts("-1");//还有可能只有一条从1到n的路径,删去其路径上任一一条边都可以使其到不了n
}
}