LightOJ1074(spfa+dfs标记负环及负环能够到达的点)
Posted frankchen831x
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了LightOJ1074(spfa+dfs标记负环及负环能够到达的点)相关的知识,希望对你有一定的参考价值。
题目链接:https://vjudge.net/problem/LightOJ-1074
题意:简化题意后就是给了一个有向图(不一定连通),n个点,m条有向边(边权可为负),求点1到其它点的最短路(其中不能到达的点或者最短距离<3的输出‘?‘,其余的输出相应的最短路即可)。
思路:因为有负权边,那么不能用dijkstra,可以用spfa来做,显然不可达的(dis[i]==inf)输出‘?‘即可,最短距离<3(dis[i]<3)的输出‘?‘,另外负环上的点以及从负环能够到达的点都直接输出‘?‘,因为他们的最短距离是无穷小。然后用spfa求最短路,并标记负环上和从负环能到达的点,用dfs标记。
AC代码:
#include<cstdio> #include<cstring> #include<cmath> #include<queue> #include<algorithm> using namespace std; const int maxn=205; const int maxm=40005; const int inf=0x3f3f3f3f; int T,cas,n,m,q,cnt,loop,bn[maxn],head[maxn],vis[maxn],dis[maxn],upd[maxn]; int f[maxn]; struct node{ int v,w,nex; }edge[maxm]; void adde(int u,int v,int w){ edge[++cnt].v=v; edge[cnt].w=w; edge[cnt].nex=head[u]; head[u]=cnt; } void dfs(int u){ for(int i=head[u];i;i=edge[i].nex){ int v=edge[i].v; if(f[v]) continue; f[v]=1; dfs(v); } } void spfa(){ queue<int> que; for(int i=1;i<=n;++i) vis[i]=0,dis[i]=inf,upd[i]=0,f[i]=0; que.push(1); vis[1]=1,dis[1]=0,upd[1]=1; while(!que.empty()){ int u=que.front();que.pop(); vis[u]=0; if(f[u]) continue; for(int i=head[u];i;i=edge[i].nex){ int v=edge[i].v,w=edge[i].w; if(dis[v]>dis[u]+w){ dis[v]=dis[u]+w; if(!vis[v]){ ++upd[v]; if(upd[v]>n){ f[u]=1; dfs(u); } else{ vis[v]=1; que.push(v); } } } } } } int main(){ scanf("%d",&T); while(T--){ printf("Case %d: ",++cas); scanf("%d",&n); cnt=0; for(int i=1;i<=n;++i) head[i]=0; for(int i=1;i<=n;++i) scanf("%d",&bn[i]); scanf("%d",&m); for(int i=1;i<=m;++i){ int u,v; scanf("%d%d",&u,&v); adde(u,v,(bn[v]-bn[u])*(bn[v]-bn[u])*(bn[v]-bn[u])); } spfa(); scanf("%d",&q); for(int i=1;i<=q;++i){ int tmp; scanf("%d",&tmp); if(f[tmp]||dis[tmp]==inf||dis[tmp]<3) printf("? "); else printf("%d ",dis[tmp]); } } return 0; }
以上是关于LightOJ1074(spfa+dfs标记负环及负环能够到达的点)的主要内容,如果未能解决你的问题,请参考以下文章
LightOJ 1074 Extended Traffic SPFA 消负环
LightOJ 1074 - Extended Traffic SPFA
Extended Traffic LightOJ - 1074 spfa判断负环