Bellman-Ford,使用队列优化的Bellman-Ford
题目地址: 某桥杯oj
题干:
问题描述
给定一个n个顶点,m条边的有向图(其中某些边权可能为负,但保证没有负环)。请你计算从1号点到其他点的最短路(顶点从1到n编号)。
输入格式
第一行两个整数n, m。
接下来的m行,每行有三个整数u, v, l,表示u到v有一条长度为l的边。
输出格式
共n-1行,第i行表示1号点到i+1号点的最短路。
样例输入
3 3
1 2 -1
2 3 -1
3 1 2
1 2 -1
2 3 -1
3 1 2
样例输出
-1
-2
-2
数据规模与约定
对于10%的数据,n = 2,m = 2。
对于30%的数据,n <= 5,m <= 10。
对于100%的数据,1 <= n <= 20000,1 <= m <= 200000,-10000 <= l <= 10000,保证从任意顶点都能到达其他所有顶点。
直接用Bellman-Ford 会超时,只能过部分数据;
需要用队列优化
优化后ac了
注释之前的是没有优化的
代码:
#include<iostream> #include<cstdio> #include<utility> #include<queue> #include<cstring> using namespace std; #define INF 1000000000 int d[20005]; int n,m,a,b,c; int u[200005]; int v[200005]; int l[200005]; int nxt[200005]; // next[e] 记录e的下一条边的标号 int first[20005]; // first[u] 是u的"第一条" 边的编号 int inq[20005]; int min(int a,int b) { return a<b?a:b; } int main() { cin>>n>>m; for(int i=0;i<n;i++) first[i]=-1; for(int i=0;i<m;i++) { scanf("%d%d%d",&a,&b,&c); u[i]=a-1; v[i]=b-1; l[i]=c; nxt[i]=first[a-1]; first[a-1]=i; } // for(int i=0;i<n;i++) // { // for(int e=first[i];e!=-1;e=nxt[e]) // cout<<e<<' '; // // cout<<endl; // } //init() for(int i=0;i<n;i++) d[i]=(i==0?0:INF); memset(inq, 0, sizeof(inq)); queue<int> q; q.push(0); while(!q.empty()) { int x=q.front(); q.pop(); inq[x]=0; for(int e=first[x];e!=-1;e=nxt[e]) { if(d[v[e]]>d[x]+l[e]) { d[v[e]]=d[x]+l[e]; if(!inq[v[e]]) { inq[v[e]]=1; q.push(v[e]); } } } } // for(int i=0;i<n;i++) // d[i]=INF; // // d[0]=0; // // // for(int i=0;i<n-1;i++) // { // for(int j=0;j<m;j++) // { // int x=u[j]; // int y=v[j]; // // if(d[x]!=INF) d[y]=min(d[y],d[x]+l[j]); // // } // } for(int i=1;i<n;i++) cout<<d[i]<<endl; }
posted on 2014-03-18 01:33 814jingqi的ACM 阅读(184) 评论(0) 编辑 收藏 举报