题意:
给出n个点和一些单向边,问从0到n+1
如果不能到则输出-1
如果能一步到则输出0
否则输出第一个到达的节点
如果两条路距离相等,则输出较小的节点
思路:
赛场上从前向后扫然后又向前推的,,,特别别扭
回来之后想了下,可以建反向边,从n+1走到0记录前驱就好了
/* *********************************************** Author :devil Created Time :2016/6/10 14:20:54 ************************************************ */ #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #include <vector> #include <queue> #include <set> #include <map> #include <string> #include <cmath> #include <stdlib.h> using namespace std; const int N=1010; const int inf=0x3f3f3f3f; struct node { int v,d; node(int a=0,int b=0):v(a),d(b){} bool operator < (const node &a) const { return d>a.d; } }; struct edge { int v,cost; edge(int a=0,int b=0):v(a),cost(b){} }; vector<edge> eg[N]; bool vis[N]; int n,m,dis[N],pre[N]; void dijkstra(int x) { memset(vis,false,sizeof(vis)); for(int i=0; i<=n+1; i++) dis[i]=inf; priority_queue<node>q; while(!q.empty()) q.pop(); dis[x]=0; q.push(node(x,0)); node tmp; while(!q.empty()) { tmp=q.top(); q.pop(); int u=tmp.v; if(vis[u]) continue; vis[u]=1; for(int i=0; i<eg[u].size(); i++) { int v=eg[tmp.v][i].v; int cost=eg[u][i].cost; if(!vis[v]&&dis[v]>dis[u]+cost) { dis[v]=dis[u]+cost; pre[v]=u; q.push(node(v,dis[v])); } else if(!vis[v]&&dis[v]==dis[u]+cost) pre[v]=min(pre[v],u); } } } int main() { //freopen("in.txt","r",stdin); int t,u,v,w; scanf("%d",&t); while(t--) { scanf("%d%d",&n,&m); for(int i=0;i<=n+1;i++) eg[i].clear(); while(m--) { scanf("%d%d%d",&u,&v,&w); eg[v].push_back(edge(u,w)); } dijkstra(n+1); if(dis[0]==inf) { printf("-1 "); continue; } if(pre[0]==n+1) { printf("0 "); continue; } printf("%d ",pre[0]); } return 0; }