思路:首先有负权值,考虑SPFA,但是数据范围所以就得用双端优化过的SPFA。
#include<bits/stdc++.h> #include<cstring> #include<string.h> #include<cstdio> using namespace std; typedef long long ll ; const int N=1e5+10; int dis[N]; int tg=0x3f3f3f3f; int t,r,p,s; bool vis1[N]; struct node { int to; int w; }; vector<node> vec[N]; void spfa(){ memset(vis1,0,sizeof(vis1)); deque<int>q; q.push_back(s); dis[s]=0; vis1[s]=1; while(!q.empty()) { int u=q.front(); q.pop_front(); vis1[u]=0; for(int i=0; i<vec[u].size(); i++) { int to=vec[u][i].to; int w=vec[u][i].w; if(dis[to]>dis[u]+w){ dis[to]=dis[u]+w; if(!vis1[to]) { int tp=q.front(); if(!q.empty()&&dis[tp]>dis[to]) /* 如果当前点到起始点的距离小于队头的tp到起始点的距离就把当前点放在队头*/ q.push_front(to); else q.push_back(to); /* 如果当前点到起始点的距离大于队头的tp到起始点的距离就把当前点放在队尾*/ vis1[to]=1; } } } } } int main() { scanf("%d%d%d%d",&t,&r,&p,&s); //n=s; int x,y,w; for(int i=1; i<=r; i++) { scanf("%d%d%d",&x,&y,&w); vec[x].push_back({y,w}), vec[y].push_back({x,w}); } for(int i=1; i<=p; i++) { scanf("%d%d%d",&x,&y,&w); vec[x].push_back({y,w}); } for(int i=0;i<N;i++) dis[i]=tg; //不要用memset!!!,不然判断是否存在的时候会存在一些不可思议的事情。 spfa(); for(int i=1; i<=t; i++) { if(dis[i]==tg) cout<<"NO PATH"<<endl; else cout<<dis[i]<<endl; } return 0; }