p1186 玛丽卡
题目描述
麦克找了个新女朋友,玛丽卡对他非常恼火并伺机报复。
因为她和他们不住在同一个城市,因此她开始准备她的长途旅行。
在这个国家中每两个城市之间最多只有一条路相通,并且我们知道从一个城市到另一个城市路上所需花费的时间。
麦克在车中无意中听到有一条路正在维修,并且那儿正堵车,但没听清楚到底是哪一条路。无论哪一条路正在维修,从玛丽卡所在的城市都能到达麦克所在的城市。
玛丽卡将只从不堵车的路上通过,并且她将按最短路线行车。麦克希望知道在最糟糕的情况下玛丽卡到达他所在的城市需要多长时间,这样他就能保证他的女朋友离开该城市足够远。
编写程序,帮助麦克找出玛丽卡按最短路线通过不堵车道路到达他所在城市所需的最长时间(用分钟表示)。
输入输出格式
输入格式:
第一行有两个用空格隔开的数N和M,分别表示城市的数量以及城市间道路的数量。1≤N≤1000,1≤M≤N*(N-1)/2。城市用数字1至N标识,麦克在城市1中,玛丽卡在城市N中。
接下来的M行中每行包含三个用空格隔开的数A,B和V。其中1≤A,B≤N,1≤V≤1000。这些数字表示在A和城市B中间有一条双行道,并且在V分钟内是就能通过。
输出格式:
输出文件的第一行中写出用分钟表示的最长时间,在这段时间中,无论哪条路在堵车,玛丽卡应该能够到达麦克处,如果少于这个时间的话,则必定存在一条路,该条路一旦堵车,玛丽卡就不能够赶到麦克处。
输入输出样例
输入样例#1:
5 7 1 2 8 1 4 10 2 3 9 2 4 10 2 5 1 3 4 7 3 5 10
输出样例#1:
27
【解析】
枚举+dijikstra的队列优化
题目大意:枚举删每一条边(枚举删的边就是道路不通的边)求最短路,找到所求的最短路的最大值。
发现枚举删的边太多一定A不了,那么思考是否需要枚举删除所有的边呢?发现,在没有删除边之前跑一边最短路,
我们删除最短路之外的对答案不造成影响,因为我们走还是走的最短路,但是最短路上的点没有被删除。这时我们是需要枚举
删除最短路上的边就可以了。
【代码】
#include<iostream> #include<cstdio> #include<queue> #include<cstring> using namespace std; #define N 1001 #define Pair pair<int,int> struct Edge { int x,y,z,next,ex; Edge(int x=0,int y=0,int z=0,int next=0,int ex=0): x(x),y(y),z(z),next(next),ex(ex){} }edge[600001]; int head[N],dis[N],pre[N],b[N*N],v[N]; int sumedge,n,m,x,y,z; void ins(int x,int y,int z) { edge[++sumedge]=Edge(x,y,z,head[x],1); head[x]=sumedge; } void diji() { memset(dis,0,sizeof(dis)); memset(pre,0,sizeof(pre)); memset(v,0,sizeof(v)); priority_queue<Pair,vector<Pair>,greater<Pair> > q;//********每次出来小的 for(int i=1;i<=n;i++)dis[i]=2147483647; dis[1]=0; q.push(make_pair(dis[1],1)); while(q.size()) { int tmp=q.top().second;q.pop(); if(v[tmp])continue; v[tmp]=1; for(int i=head[tmp];i;i=edge[i].next) { if(dis[tmp]+edge[i].z<dis[edge[i].y]&&edge[i].ex) { dis[edge[i].y]=dis[tmp]+edge[i].z; q.push(make_pair(dis[edge[i].y],edge[i].y)); pre[edge[i].y]=i; } } } } int main() { scanf("%d%d",&n,&m); for(int i=1;i<=m;i++) { scanf("%d%d%d",&x,&y,&z); ins(x,y,z); ins(y,x,z); } diji(); for(int i=pre[n];i;i=pre[edge[i].x]) { b[++b[0]]=(i+1)/2; } int maxx=-1; for(int i=1;i<=b[0];i++) { edge[b[i]*2].ex=0;//无向图双向删边 edge[b[i]*2-1].ex=0; diji(); edge[b[i]*2].ex=1; edge[b[i]*2-1].ex=1; maxx=max(maxx,dis[n]); } printf("%d\n",maxx); return 0; }