P2829 大逃离

P2829 大逃离

题意简述:一个n个节点m条边的无向有权图,将d(度数)<k的点删除,求 \(1->n\) 的次短路

首先回顾一下我们写次短路的经典Trick:以S,T分别为源点求两次最短路,然后建立一个最短路树(并不用真的去建它,只需要将所有在最短路上的边打上一个标记就好了)

然后遍历每条边 \((u,v,w)\),次短路的组成即为 
\(min\) \({dis_s[u]+w+dis_t[v] }\)

然后这题其实有个偷懒的地方:

注意如果有多条路径都是最短路径,那么他们都不能叫第2短路径

这提示我们甚至不用记录最短路,直接将边集遍历一遍,
对于所有满足$dis_s[u]+w+dis_t[v] <dis_s[t] $ 的边\((u,v,w)\)
最小化\(dis_s[u]+w+dis_t[v]\)

然后还要注意的是:在本题中可能有u,v,相同但是w不同的边,这样的的“重边”不能对d(度数)产生贡献

所以我们要去重,这里我用了Map<pair,bool>
但其实可以将(x,y)压成一个\(id=x*n+y\)应该会比我的快不少,但是我懒但是我认为Map在n不这么小的情况下能发挥作用而id貌似不能

(其实用vector存图然后unique一下貌似更好)
坏了我成小丑了
算了不管了反正写了也过了
时间复杂度就是正常dijkstra复杂度\(O(mlogm)\)

Code:

#include<bits/stdc++.h>
#define int long long
const int N=1e5+5;
const int inf=1e17;
using namespace std;
int n,m,k,e_cnt,res,ans;
struct Edge{
    int to,nxt,w;
}e[N<<1];
int d[N],dis_s[N],dis_t[N],vis[N],head[N];
int X[N<<1],Y[N<<1],W[N<<1];
void add(int x,int y,int w)
{
    e[++e_cnt]=(Edge){y,head[x],w};
    head[x]=e_cnt;d[x]++;
}
void init(int a[],int val)
{
    for(int i=1;i<=n;i++){a[i]=val;}
}
struct Node{
    int id,w;
    bool operator<(const Node &a)const{
        return a.w<w;
    }
};
priority_queue<Node> Q;
void dijkstra(int s,int dis[])
{
    dis[s]=0;
    Q.push((Node){s,0});
    while(!Q.empty())
    {
        int u=Q.top().id;Q.pop();
        if(vis[u])continue;
        vis[u]=1;
        for(int i=head[u],v;i;i=e[i].nxt)
        {
            v=e[i].to;
            if(d[v]<k)continue;
            if(dis[v]>dis[u]+e[i].w)
            {
                dis[v]=dis[u]+e[i].w;
                Q.push((Node){v,dis[v]});
            }
        }
    }
}
#define mp(x,y) make_pair(x,y)
map<pair<int,int>,bool> Map;
void work()
{
    cin>>n>>m>>k;
    init(dis_s,inf);
    init(dis_t,inf);
    for(int i=1;i<=m;i++)
    {
        scanf("%lld%lld%lld",&X[i],&Y[i],&W[i]);
        if(X[i]==Y[i])continue;
        add(X[i],Y[i],W[i]);
        add(Y[i],X[i],W[i]);
        X[i+m]=Y[i];
        Y[i+m]=X[i];
        W[i+m]=W[i];
        d[X[i]]-=Map[mp(X[i],Y[i])];
        d[Y[i]]-=Map[mp(Y[i],X[i])];
        Map[mp(X[i],Y[i])]=Map[mp(Y[i],X[i])]=1;
    }
    d[1]=d[n]=inf;
    dijkstra(1,dis_s);
    init(vis,0);
    dijkstra(n,dis_t);
    ans=inf;
    if(dis_s[n]==inf)
    {
        cout<<-1;
        return ;
    }
    m<<=1;
    for(int i=1;i<=m;i++)
    {
        if(X[i]==Y[i])continue;
        if(dis_s[X[i]]+W[i]+dis_t[Y[i]]!=dis_s[n])
        {
            ans=min(ans,dis_s[X[i]]+W[i]+dis_t[Y[i]]);
        }
    }
    printf("%lld\n",ans==inf ? -1 : ans);
}
#undef int
int main()
{
    freopen("P2829.in","r",stdin);freopen("P2829.out","w",stdout);
    work();
    return 0;
}

posted @ 2024-12-06 11:54  liuboom  阅读(27)  评论(0)    收藏  举报