最短路的模板题。。。
SPFA打过一遍。 但今天终于看懂了Dijkstra和堆优化,走一发。
Dijkstra的思想很简单,每次找到和起点dis最小的点,再将该点到其他有边相连的点的dis更新。重复n次即可。记得判断哪个点用过。
裸Dijkstra复杂度为O(n^2),但对于10000的数据能跑90分。难以置信!
CODE
#include<cstdio> #include<vector> #include<cstring> using namespace std; inline void read(int &x) { x=0; char ch=getchar(); while (ch<'0'||ch>'9') ch=getchar(); while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar(); } const int INF=2147483647,N=10005,M=500005; vector <int> a[N],l[N]; int n,m,i,j,dis[N],s,x,y,z; bool f[N]; int main() { read(n); read(m); read(s); for (i=1;i<=m;++i) { read(x); read(y); read(z); a[x].push_back(y); l[x].push_back(z); } memset(f,true,sizeof(f)); for (i=1;i<=n;++i) dis[i]=INF; dis[s]=0; for (i=1;i<=n;++i) { x=y=INF; for (j=1;j<=n;++j) if (dis[j]<y&&f[j]) y=dis[x=j]; f[x]=0; for (j=0;j<a[x].size();++j) dis[a[x][j]]=min(dis[a[x][j]],dis[x]+l[x][j]); } for (i=1;i<=n;++i) printf("%d ",dis[i]); return 0; }
仔细看找出最小dis值的过程,发现总是取出最小的,果断堆优化。(虽然线段树也可以)
用结构体定义。
#include<cstdio> #include<vector> #include<queue> using namespace std; inline void read(int &x) { x=0; char ch=getchar(); while (ch<'0'||ch>'9') ch=getchar(); while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar(); } const int INF=2147483647,N=10005,M=500005; vector <int> a[N],l[N]; int dis[N],n,m,i,x,y,z,s; bool f[N]; struct data { int v,num; bool operator <(const data &x) const { return x.v<v; } }; priority_queue <data> tree; int main() { read(n); read(m); read(s); for (i=1;i<=m;++i) { read(x); read(y); read(z); a[x].push_back(y); l[x].push_back(z); } for (i=1;i<=n;++i) dis[i]=INF; dis[s]=0; tree.push((data){0,s}); while (!tree.empty()) { int now=tree.top().num; tree.pop(); if (f[now]) continue; f[now]=1; for (i=0;i<a[now].size();++i) { int k=a[now][i]; if (dis[k]>dis[now]+l[now][i]) { dis[k]=dis[now]+l[now][i]; tree.push((data){dis[k],k}); } } } for (i=1;i<=n;++i) printf("%d ",dis[i]); return 0; }