概述
题目描述
麦克找了个新女朋友,玛丽卡对他非常恼火并伺机报复。
因为她和他们不住在同一个城市,因此她开始准备她的长途旅行。
在这个国家中每两个城市之间最多只有一条路相通,并且我们知道从一个城市到另一个城市路上所需花费的时间。
麦克在车中无意中听到有一条路正在维修,并且那儿正堵车,但没听清楚到底是哪一条路。无论哪一条路正在维修,从玛丽卡所在的城市都能到达麦克所在的城市。
玛丽卡将只从不堵车的路上通过,并且她将按最短路线行车。麦克希望知道在最糟糕的情况下玛丽卡到达他所在的城市需要多长时间,这样他就能保证他的女朋友离开该城市足够远。
编写程序,帮助麦克找出玛丽卡按最短路线通过不堵车道路到达他所在城市所需的最长时间(用分钟表示)。
输入格式:
第一行有两个用空格隔开的数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分钟内是就能通过。
输出格式:
输出文件的第一行中写出用分钟表示的最长时间,在这段时间中,无论哪条路在堵车,玛丽卡应该能够到达麦克处,如果少于这个时间的话,则必定存在一条路,该条路一旦堵车,玛丽卡就不能够赶到麦克处。
意思就是最短路但有一条边不能走,看到题,最暴力的想法,枚举删掉每一条边,然后求m-1次最短路取最大值。可这样做无疑是超时的。怎么办?想了10分钟。找了找规律想了想DP发现不具有最优子结构,因此无法DP。想起了昨天cjr神犇教我的次小生成树算法(最小生成树后找不在生成树上的边来替换(替换时不用找每一条生成树边,只需要找生成树上两点之间权值最大边,倍增实现))。对于删掉一条边的最短路,如果删掉的边不影响最优解,那么将不会影响答案。如果删掉的边是最优解上的边,我们才需要重新来找。所以我们可以找出最优解的边,然后一一删去来求最短路最大值。
#include<bits/stdc++.h>
using namespace std;
const int MAXN=1e6;
int head[MAXN],cnt=0,dis[MAXN],pre[MAXN],ban[MAXN],ks,js,ans=0;
struct edge{
int to,next,w;
}e[MAXN<<2];
struct hnd{
int u,d;
bool operator<(const hnd&rhs)const{
return d>rhs.d;
}
};
priority_queue<hnd>q;
inline void add(int u,int v,int w){e[++cnt]=(edge){v,head[u],w},head[u]=cnt;}
void dij(int u){
memset(dis,0x7f,sizeof(dis));
dis[u]=0;q.push((hnd){u,dis[u]});
while(!q.empty()){
hnd x=q.top();q.pop();
int u=x.u;
if(x.d!=dis[u])continue;
for(int i=head[u];i;i=e[i].next){
int v=e[i].to,w=e[i].w;
if(dis[u]+w<dis[v]){
dis[v]=dis[u]+w;
pre[v]=u;
q.push((hnd){v,dis[v]});
}
}
}
}
void dijban(int u){
memset(dis,0x7f,sizeof(dis));
dis[u]=0;q.push((hnd){u,dis[u]});
while(!q.empty()){
hnd x=q.top();q.pop();
int u=x.u;
if(x.d!=dis[u])continue;
for(int i=head[u];i;i=e[i].next){
int v=e[i].to,w=e[i].w;
if(u==ks&&v==js||v==ks&&u==js)continue;
if(dis[u]+w<dis[v]){
dis[v]=dis[u]+w;
pre[v]=u;
q.push((hnd){v,dis[v]});
}
}
}
}
int n,m,tem1,tem2,tem3;
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++){
scanf("%d%d%d",&tem1,&tem2,&tem3);
add(tem1,tem2,tem3);
add(tem2,tem1,tem3);
}
dij(n);
int times=0;
ban[++times]=1;
for(int i=pre[1];i;i=pre[i]){
ban[++times]=i;
}
for(int i=1;i<=times-1;i++){
ks=ban[i],js=ban[i+1];
// printf("%d %dn",ks,js);
dijban(n);
ans=max(ans,dis[1]);
}
printf("%dn",ans);
return 0;
}
最后
以上就是怕孤单睫毛膏为你收集整理的玛丽卡的全部内容,希望文章能够帮你解决玛丽卡所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复