思路:三遍SPFA,前两遍对两个GPS分别SPFA,记录前驱边和前驱节点,并根据这个将第二场图的边权修改。
60tps。。。样例没过。。。求助QAQ
假如算法错误,请指出错误之处qwq
#include<cstdio>
#include<deque>
const int M=1e4+5,INF=0x7fffffff;
int n,m,cnt[3],h[3][M];
int d[3][M],preE[3][M],preN[3][M];
struct Edge{
int to,val,nx;
}e[3][M*5];
inline void Add(int x,int y,int val,int id){
e[id][++cnt[id]]=(Edge){y,val,h[id][x]};h[id][x]=cnt[id];
}
inline void SPFA(Edge*e,int*h,int*d,int*preE,int*preN){
static bool vis[M];
std::deque<int>q;
int u,v,E;
for(u=1;u<=n;++u)d[u]=INF;
d[1]=0;q.push_back(1);
while(!q.empty()){
vis[u=q.front()]=0;q.pop_front();
for(E=h[u];E;E=e[E].nx){
v=e[E].to;
if(d[u]+e[E].val<d[v]){
d[v]=d[u]+e[E].val;
preE[v]=E;preN[v]=u;
if(!vis[v]){
vis[v]=1;
if(d[v]<d[q.front()])q.push_front(v);
else q.push_back(v);
}
}
}
}
}
inline void Add(int id){
int t=n;
while(preN[id][t]){
--e[2][preE[id][t]].val;
t=preN[id][t];
}
}
signed main(){
int i;
scanf("%d%d",&n,&m);
for(i=1;i<=m;++i){
int x,y,z;
scanf("%d%d",&x,&y);
Add(x,y,2,2);
scanf("%d",&z);
Add(x,y,z,0);
scanf("%d",&z);
Add(x,y,z,1);
}
SPFA(e[0],h[0],d[0],preE[0],preN[0]);Add(0);
// for(i=1;i<=n;++i)printf("%d ",d[0][i]);printf("\n");
SPFA(e[1],h[1],d[1],preE[1],preN[1]);Add(1);
// for(i=1;i<=n;++i)printf("%d ",d[1][i]);printf("\n");
SPFA(e[2],h[2],d[2],preE[2],preN[2]);
printf("%d",d[2][n]);
}