题目描述
如题,给出一个有向图,请输出从某一点出发到所有点的最短路径长度。
输入输出格式
输入格式:
第一行包含三个整数 N、M、S ,分别表示点的个数、有向边的个数、出发点的编号。
接下来
M
行每行包含三个整数
输出格式:
一行,包含
输入输出样例
输入样例#1:
4 6 1
1 2 2
2 3 2
2 4 1
1 3 5
3 4 3
1 4 4
输出样例#1:
0 2 4 3
说明
时空限制:
1000ms,128M
数据规模:
对于 20% 的数据: N≤5,M≤15
对于 40% 的数据: N≤100,M≤10000
对于 70% 的数据: N≤1000,M≤100000
对于 100% 的数据: N≤10000,M≤500000
样例说明:
solution
40% 的数据,Floyd模板题
70% 的数据,dijkstra模板题
100% 的数据,spfa/堆优化的dijkstra模板题
code
当然是四种算法都有啦!
#include<queue>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
template<typename T>
void input(T &x) {
x=0; T a=1;
register char c=getchar();
for(;c<'0'||c>'9';c=getchar())
if(c=='-') a=-1;
for(;c>='0'&&c<='9';c=getchar())
x=x*10+c-'0';
x*=a;
return;
}
namespace __Floyd {
const int MAXN=110;
const int inf=2147483647;
int dis[MAXN][MAXN];
void Floyd(int n,int m,int s) {
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
dis[i][j]=inf*(i!=j);
for(int i=1;i<=m;i++) {
int u,v,w;
input(u),input(v),input(w);
if(w<dis[u][v]) dis[u][v]=w;
}
for(int k=1;k<=n;k++)
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
if(i!=j&&i!=k&&j!=k&&dis[i][k]!=inf&&dis[k][j]!=inf)
dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);
for(int i=1;i<=n;i++)
printf("%d ",dis[s][i]);
return;
}
}
namespace __dijkstra {
const int MAXN=1010;
const int inf=2147483647;
int G[MAXN][MAXN];
int dis[MAXN];
bool vis[MAXN];
void dijkstra(int n,int m,int s) {
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
G[i][j]=inf*(i!=j);
for(int i=1;i<=m;i++) {
int u,v,w;
input(u),input(v),input(w);
if(w<G[u][v]) G[u][v]=w;
}
for(int i=1;i<=n;i++)
dis[i]=G[s][i],vis[i]=false;
vis[s]=true;
for(int k=1;k<n;k++) {
int Min=inf,u=-1;
for(int i=1;i<=n;i++)
if(!vis[i]&&dis[i]<Min)
Min=dis[u=i];
if(u==-1) break;
vis[u]=true;
for(int v=1;v<=n;v++)
if(G[u][v]<inf&&dis[u]+G[u][v]<dis[v])
dis[v]=dis[u]+G[u][v];
}
for(int i=1;i<=n;i++)
printf("%d ",dis[i]);
return;
}
}
namespace __spfa {
const int MAXN=10010;
const int MAXM=500010;
const int inf=2147483647;
struct Edge {
int u,v,w,next;
Edge(int u=0,int v=0,int w=0,int next=0):
u(u),v(v),w(w),next(next) {}
};
Edge edge[MAXM];
int head[MAXN],cnt;
void addedge(int u,int v,int w) {
edge[++cnt]=Edge(u,v,w,head[u]);
head[u]=cnt;
return;
}
queue<int> q;
bool inq[MAXN];
int dis[MAXN];
void spfa(int n,int m,int s) {
for(int i=1;i<=m;i++) {
int u,v,w;
input(u),input(v),input(w);
addedge(u,v,w);
}
for(int i=1;i<=n;i++)
dis[i]=inf,inq[i]=false;
q.push(s);
inq[s]=true;
dis[s]=0;
while(!q.empty()) {
int u=q.front();
q.pop();
inq[u]=false;
for(int i=head[u];i;i=edge[i].next) {
int v=edge[i].v;
if(dis[u]+edge[i].w<dis[v]) {
dis[v]=dis[u]+edge[i].w;
if(!inq[v]) {
q.push(v);
inq[v]=true;
}
}
}
}
for(int i=1;i<=n;i++)
printf("%d ",dis[i]);
return;
}
}
namespace __dijkstra_heap {
const int MAXN=10010;
const int MAXM=500010;
const int inf=2147483647;
struct Edge {
int u,v,w,next;
Edge(int u=0,int v=0,int w=0,int next=0):
u(u),v(v),w(w),next(next) {}
};
Edge edge[MAXM];
int head[MAXN],cnt;
void addedge(int u,int v,int w) {
edge[++cnt]=Edge(u,v,w,head[u]);
head[u]=cnt;
return;
}
struct Data {
int dis,x;
Data(int dis=0,int x=0):
dis(dis),x(x) {}
bool operator < (const Data &q)const {
return dis<q.dis;
}
bool operator > (const Data &q)const {
return dis>q.dis;
}
};
priority_queue<Data,vector<Data>,greater<Data> > heap;
int dis[MAXN];
bool vis[MAXN];
void dijkstra(int n,int m,int s) {
for(int i=1;i<=m;i++) {
int u,v,w;
input(u),input(v),input(w);
addedge(u,v,w);
}
for(int i=1;i<=n;i++)
dis[i]=inf,vis[i]=false;
dis[s]=0;
heap.push(Data(dis[s],s));
while(!heap.empty()) {
Data now=heap.top();
heap.pop();
int u=now.x;
if(vis[u]) continue;
vis[u]=true;
for(int i=head[u];i;i=edge[i].next) {
int v=edge[i].v;
if(dis[u]+edge[i].w<dis[v]) {
dis[v]=dis[u]+edge[i].w;
heap.push(Data(dis[v],v));
}
}
}
for(int i=1;i<=n;i++)
printf("%d ",dis[i]);
return;
}
}
int main() {
int n,m,s;
input(n),input(m),input(s);
if(n<=100) __Floyd::Floyd(n,m,s);
else if(n<=1000) __dijkstra::dijkstra(n,m,s);
else if(m<=10000) __spfa::spfa(n,m,s);
else __dijkstra_heap::dijkstra(n,m,s);
puts("");
return 0;
}