P2829 大逃离

P2829 大逃离

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

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

然后遍历每条边 (u,v,w),次短路的组成即为 
min diss[u]+w+dist[v]

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

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

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

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

所以我们要去重,这里我用了Map<pair,bool>
但其实可以将(x,y)压成一个id=xn+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 @   liuboom  阅读(2)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 没有源码,如何修改代码逻辑?
· PowerShell开发游戏 · 打蜜蜂
· 在鹅厂做java开发是什么体验
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
点击右上角即可分享
微信分享提示