题目:玛丽卡
思路:
先在图中求出一条最短路径。
假设删掉的边不在最短路径上,他对答案是没有贡献的,可以忽略。
所以接下来可以枚举最短路径上的边,将其标记,再跑最短路。
很多题解都写的spfa,这里用优先队列优化的dijkstra,复杂度大概是 O(n*(n+m)logn),但是luogu玄学评测机竟然卡过去了STO,听说此题也基本没有更优的算法了。
代码:
#include<bits/stdc++.h>
using namespace std;
#define maxn 1000
#define maxm 1000000
#define inf (1<<29)
struct Pair{
int y,z,fa;
Pair(){}
Pair(int yy,int zz,int faa=0) {
y=yy,z=zz,fa=faa;
}
bool operator < (const Pair oth) const {
return z>oth.z;
}
};
int n,m;
vector<Pair> a[maxn+5];
void readin(){
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++) {
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
a[x].push_back(Pair(y,z));
a[y].push_back(Pair(x,z));
}
}
int fa[maxn+5]={0};
int U,V;
int dijkstra(){
memset(fa,0,sizeof(fa));
int dist[maxn+5];
for(int i=1;i<=n;i++) dist[i]=inf;
dist[1]=0;
priority_queue<Pair> que;
que.push(Pair(1,0));
while(!que.empty()) {
Pair h=que.top();
que.pop();
if(fa[h.y]) continue;
else fa[h.y]=h.fa;
for(int i=0;i<a[h.y].size();i++){
Pair x=a[h.y][i];
if((h.y==U&&x.y==V)||(x.y==U&&h.y==V)) continue;
if(h.z+x.z<dist[x.y]) {
dist[x.y]=h.z+x.z;
que.push(Pair(x.y,dist[x.y],h.y));
}
}
}
return dist[n];
}
vector<int> wy;
void find_way(){
int x=n;
while(x!=0) {
wy.push_back(x);
x=fa[x];
}
}
int main(){
readin();
int ans=dijkstra();
find_way();
for(int i=0;i<wy.size()-1;i++){
U=wy[i+1],V=wy[i];
ans=max(ans,dijkstra());
}
printf("%d",ans);
return 0;
}