[JZOJ5279]香港记者题解--最短路图

[JZOJ5279]香港记者题解--最短路图

题目链接

过 于 暴 力

分析

有一个naiive的想法就是从1到n跑最短路,中途建图,然后在图上按字典序最小走一遍,然而·这是不行的,你这样跳不一定能跳到终点.

所以应该是在1到n的最短路图上跳,怎么求有向图短路图?你跑一遍1到n得到\(dist1[]\),n到1的最短路得到\(dist[2]\),然后从1 BFS,对于原图一条\(u\),连向\(v\)的边,若\(dis1[u]+dis2[v]+dis(u,v)\)等于1到n的最短路距离,则最短路图上\(u\)\(v\)也连一条相同的边

然后模拟一遍走最小的点就好了

结果跑了个rank倒2,看他们直接倒着一遍dij就完了,现在还搞不懂为什么...

另外我用了一次DFS就直接爆栈了,全改成了BFS

代码

/*
  code by RyeCatcher
*/
const int maxn=800005;
const ll inf=1e17+19260817;
struct Edge{
    int ne,to,o;
    ll dis;
}edge[maxn<<1];
int h[maxn],num_edge=1;
inline void add_edge(int f,int to,ll c,int o){
    edge[++num_edge].ne=h[f];
    edge[num_edge].to=to;
    edge[num_edge].dis=c;
    edge[num_edge].o=o;
    h[f]=num_edge;
}
int n,m,tag[maxn];
ll dis[maxn][2],all_dis;
struct SE{
    int ne,to;
    ll dis;
}se[maxn<<1];
int sh[maxn],num_se=1;
inline void add_se(int f,int to,ll c){
    se[++num_se].ne=sh[f];
    se[num_se].to=to;
    se[num_se].dis=c;
    sh[f]=num_se;
}
bool vis[maxn];int g[maxn][2];
inline void dijsktra(int st,int id){
    Heap q;int u,v;
    for(ri i=1;i<=n;i++)dis[i][id]=inf,vis[i]=0;
    while(q.size())q.pop();
    q.push(pii(0,st));dis[st][id]=0,g[st][id]=1;
    while(q.size()){
        u=q.top().second;q.pop();
        if(vis[u])continue;
        vis[u]=1;
        for(ri i=h[u];i;i=edge[i].ne){
            v=edge[i].to;
            if(edge[i].o!=id)continue;
            if(dis[v][id]>dis[u][id]+edge[i].dis){
                dis[v][id]=dis[u][id]+edge[i].dis;
                g[v][id]=1;
                q.push(pii(dis[v][id],v));
            }
        }
    }
    return ;
}
void pre_bfs(){
    int u,v;
    queue<int> q;
    q.push(1);memset(vis,0,sizeof(vis));
    while(q.size()){
        u=q.front();q.pop();
        vis[u]=1;
        for(ri i=h[u];i;i=edge[i].ne){
            v=edge[i].to;
            if(dis[u][0]+dis[v][1]+edge[i].dis==all_dis){
                add_se(u,v,edge[i].dis);
                if(!vis[v]){
                    q.push(v);
                    vis[v]=1;
                }
            }
        }
    }
    return ;
}
int path[maxn],tot=0;
inline void bfs(){
    queue <int> q;
    memset(vis,0,sizeof(vis));
    q.push(1);
    int path[maxn],tot=0;
    int u,v,tt,vv,dist=0,dd;
    while(q.size()){
        u=q.front();q.pop();vis[u]=1;
        path[++tot]=tag[u];
        if(u==n){
            printf("%lld\n",all_dis);
            for(ri i=1;i<=tot;i++)printf("%d ",path[i]);
            puts("");
            exit(0);
        }
        tt=1e9+7,vv=0;
        for(ri i=sh[u];i;i=se[i].ne){
            v=se[i].to;
            if(v==n){
                vv=v,dd=se[i].dis;
                break;
            }
            if(vis[v]||!(g[v][1]&&g[v][0]))continue;
            if(tag[v]<tt){
                tt=tag[v],vv=v,dd=se[i].dis;
            }
        }
        if(!vv)break;
        q.push(vv),dist+=dd;
    }
}
int main(){
    int x,y,z;
    //freopen("journalist7.in","r",stdin);
    //freopen("wtf.out","w",stdout);
    read(n),read(m);
    for(ri i=1;i<=n;i++){
        read(tag[i]);
    }
    for(ri i=1;i<=m;i++){
        read(x),read(y),read(z);
        add_edge(x,y,z,0);
        add_edge(y,x,z,1);
    }
    dijsktra(1,0),dijsktra(n,1);
    all_dis=dis[n][0];
    pre_bfs();
    bfs();
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/Rye-Catcher/p/9883788.html
今日推荐