sdut3562-求字典序最小的最短路 按顶点排序后spfa的反例
Posted 狡啮之仰
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了sdut3562-求字典序最小的最短路 按顶点排序后spfa的反例相关的知识,希望对你有一定的参考价值。
首先我们可以这么搞...倒序建图,算出源点s附近的点距离终点的距离,然后判断一下,终点是否能跑到源点
能跑到的话呢,我们就判断s周围的点是否在最短路上,然后我们选编号最小的点就好了
代码
#include <iostream> #include <cstdio> #include <algorithm> #include <queue> #include <vector> #include <cstring> using namespace std; const int maxn=1005; const int INF=1e9; int n,m,dist[maxn],pre[maxn];bool vis[maxn]; struct node{ int v,w;node(){};node(int v,int w):v(v),w(w){}; }; bool cmp(node a,node b){ return a.v<b.v; } vector<node> G[maxn]; vector<node> St; void init(){ for(int i=0;i<maxn;++i) G[i].clear();St.clear(); for(int i=0;i<maxn;++i) dist[i]=INF; memset(vis,0,sizeof(vis)); memset(pre,-1,sizeof(pre)); } int main(){ int T;scanf("%d",&T); while(T--){ scanf("%d%d",&n,&m); init();int a,b,c; for(int i=0;i<m;++i){ scanf("%d%d%d",&a,&b,&c); G[b].push_back(node(a,c)); if(a==0) St.push_back(node(b,c)); //G[b].push_back(node(a,c)); } queue<int> Q;Q.push(n+1);vis[n+1]=1;dist[n+1]=0; while(Q.size()){ int now=Q.front();Q.pop();vis[now]=0; for(int i=0;i<G[now].size();++i){ int to=G[now][i].v,tw=G[now][i].w; if(dist[to]>dist[now]+tw){ dist[to]=dist[now]+tw; pre[to]=now; if(!vis[to]) { Q.push(to);vis[to]=1; } } } } if(dist[0]==INF) { printf("-1\n");continue; } int flag=0,ans=INF; for(int i=0;i<St.size();++i){ int to=St[i].v,tw=St[i].w; if(tw+dist[to]==dist[0]){ if(to==n+1){ flag=1;break; } ans=min(ans,to); } } if(flag) printf("0\n"); else printf("%d\n",ans); } return 0; }
下面这种做法是错误做法,那就是先对每个邻接表按顶点标号大小排序,然后跑一遍spfa
一般的数据都能正常出解,但是对于这一组数据,哈哈,怕是翻车了
2 4
0 1 2
1 2 1
0 2 3
2 3 1
松弛完1,直接松弛0,2这条边,于是0,1,2,3这条路径不会被考虑了,
于是答案就是2,而不是正确的1,1被早来的0,2这条边从后面架空了
附上错误代码
#include <iostream> #include <cstdio> #include <algorithm> #include <queue> #include <vector> #include <cstring> using namespace std; const int maxn=1005; const int INF=1e9; int n,m,dist[maxn],pre[maxn];bool vis[maxn]; struct node{ int v,w;node(){};node(int v,int w):v(v),w(w){}; }; bool cmp(node a,node b){ return a.v<b.v; } vector<node> G[maxn]; void init(){ for(int i=0;i<maxn;++i) G[i].clear(); for(int i=0;i<maxn;++i) dist[i]=INF; memset(vis,0,sizeof(vis)); memset(pre,-1,sizeof(pre)); } int main(){ int T;scanf("%d",&T); while(T--){ scanf("%d%d",&n,&m); init();int a,b,c; for(int i=0;i<m;++i){ scanf("%d%d%d",&a,&b,&c); G[a].push_back(node(b,c)); //G[b].push_back(node(a,c)); } for(int i=0;i<maxn;++i){ if(G[i].size()) sort(G[i].begin(),G[i].end(),cmp); } queue<int> Q;Q.push(0);vis[0]=1;dist[0]=0; while(Q.size()){ int now=Q.front();Q.pop();vis[now]=0; for(int i=0;i<G[now].size();++i){ int to=G[now][i].v,tw=G[now][i].w; if(dist[to]>dist[now]+tw){ dist[to]=dist[now]+tw; pre[to]=now; if(!vis[to]) { Q.push(to);vis[to]=1; } } } } if(dist[n+1]==INF) { printf("-1\n");continue; } int i; for(i=0;i<G[0].size();++i) { if(G[0][i].v==n+1&&G[0][i].w==dist[n+1]) break; } if(i<G[0].size()) {printf("0\n");continue;} for(i=n+1;pre[i]!=0;i=pre[i]); printf("%d\n",i); } return 0; }
由于路径不算原点,所以说
0 2 3>0 1 2 3
也就是 2 3>1 2 3
所以在源点需要特判
以上是关于sdut3562-求字典序最小的最短路 按顶点排序后spfa的反例的主要内容,如果未能解决你的问题,请参考以下文章