题解 [USACO07FEB]银牛派对Silver Cow Party(luoguP1821)

蒟蒻刚学Dijkstra

(是根据一位初一就AK了NOIP-PJ2018的神仙的博客学的)

什么堆之类的优化都不会

(其实我连queue也不会用)

只好写一个不带任何优化的双向Dijkstra

不过只要吸氧就能过

Code

#pragma GCC optimize(2)
//手动O2优化
#include<bits/stdc++.h>
using namespace std;
const long long inf = 2147483647;
long long dis[2000];
long long ans[2000];//代表每个点的最短路径(去+回)
int eh[2000] = {0};//邻接表
bool used[2000] = {0};//代表这个点的最短路径是否确定
struct EE{
    int st,val,ne;
}edge[200000];//结构体存边
int n,m,s,nw;
long long minn;
inline void Read(){
    scanf("%d%d%d",&n,&m,&s);
    for(int i = 1;i<=m;i++){
        int x;
      
        scanf("%d%d%d",&x,&edge[i].st,&edge[i].val);
        edge[i].ne = eh[x];
        eh[x] = i; //存入邻接表
    }
}
void findmin(){
    for(int i = 1;i<=n;i++){
        if(!used[i]&&minn>dis[i]){
            minn = dis[i];
            nw = i;
        }
    }
}
inline void dijkstra1(){ //单源最短路径
    if(used[nw])return;
    used[nw] = 1;
    for(int i = eh[nw];i!=0;i = edge[i].ne)
        if(!used[edge[i].st])dis[edge[i].st] = min(dis[edge[i].st],dis[nw]+edge[i].val);//dijkstra基本操作
    minn = inf;
    findmin(); //寻找剩下点中原点到这个点最短路径最短的
    dijkstra1();
}
inline void dijkstra2(){ //单终点最短路径
    used[nw] = 1;
    if(used[s])return;//如果到终点的最短路径确定下来就停止
    for(int i = eh[nw];i!=0;i = edge[i].ne) 
        if(!used[edge[i].st])dis[edge[i].st] = min(dis[edge[i].st],dis[nw]+edge[i].val);
    minn = inf;
    findmin();
    dijkstra2();
}
inline void Print(){//输出,找出最长的最短路径
    long long c = -1;
    for(int i= 1;i<=n;i++)if(ans[i]>c) c = ans[i];
    printf("%lld",c); 
}   
int main(){

    Read();
    for(int i = 1;i<=n;i++)dis[i] = inf;
    for(int i = 1;i<=n;i++){
        dis[i] = 0;
        nw = i;
        dijkstra2();
        memset(used,0,sizeof(used));
        ans[i] += dis[s];
        for(int i = 1;i<=n;i++)dis[i] = inf;
    } // 第一次Dijkstra(去)
    nw = s;
    dis[s] = 0;
    dijkstra1();// 第二次Dijkstra(回)
    for(int i = 1;i<=n;i++)ans[i]+=dis[i]; 
    Print();
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/LJA001100/p/luoguP1821.html