传送门
这道题直接使用暴力的dij是不行的,会超时,那怎么办呢?我们可以用优先队列和领接表优化一下就可以大大降低时间复杂度和空间复杂度,下面给出代码
#include<bits/stdc++.h>
#define lson l, mid, root << 1
#define rson mid + 1, r, root << 1 | 1
#define father l , r , root
#define lowbit(x) ( x & ( - x ) )
#define mod 1000000007
#define ll long long
using namespace std;
const int maxn = 100005;
const int inf = 0x3f3f3f3f;
int dis[maxn];
bool vis[maxn];
int n,m,s,e,cnt=1;
int head[maxn];
int to[maxn];
int nxt[maxn];
int val[maxn];
int from[maxn];
struct node{
int num,len;
bool operator < (const node&a) const{
return a.len<len;
}
};
int dij(){
priority_queue<node>q;
memset(vis,0,sizeof(vis));
for(int i=1;i<=n;i++) dis[i]=inf;
dis[s]=0;
node temp;
temp.num=s;
temp.len=0;
q.push(temp);
while(q.size()){
temp=q.top();
q.pop();
if(vis[temp.num])
continue;
vis[temp.num]=1;
int flag=head[temp.num];
while(flag!=-1){
if(dis[to[flag]]>dis[temp.num]+val[flag]&&(!vis[to[flag]])){
dis[to[flag]]=dis[temp.num]+val[flag];
node tmp;
tmp.len=dis[to[flag]];
tmp.num=to[flag];
q.push(tmp);
}
flag=nxt[flag];
}
}
return dis[e];
}
void add(int a,int b,int c){
from[cnt]=a;
to[cnt]=b;
val[cnt]=c;
nxt[cnt]=head[a];
head[a]=cnt++;
}
int main(){
scanf("%d%d%d%d",&n,&m,&s,&e);
memset(head,-1,sizeof(head));
for(int i=0;i<m;i++){
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
add(x,y,z);
add(y,x,z);//双向边
}
int k;
int ans=dij();
scanf("%d",&k);
if(ans!=inf){
ans/=2;
}
for(int i=0;i<k;i++){
int x;
scanf("%d",&x);
int c;
c=val[x*2];
val[x*2]=0;
val[x*2-1]=0;
ans=min(ans,dij());
val[x*2]=c;
val[x*2-1]=c;
}
printf("%d\n",ans==inf?-1:ans);
return 0;
}