Harry Potter and the Final Battle HDU-3986 Dijkstra

题目链接: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 
	}
}

猜你喜欢

转载自blog.csdn.net/qq_35320178/article/details/81807999