洛谷 P1186 玛丽卡

题目:玛丽卡

思路:
先在图中求出一条最短路径。
假设删掉的边不在最短路径上,他对答案是没有贡献的,可以忽略。
所以接下来可以枚举最短路径上的边,将其标记,再跑最短路。
很多题解都写的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;
}

猜你喜欢

转载自blog.csdn.net/rabbit_ZAR/article/details/81395016