1.dijkstra算法
因为数组的实在太low...如果未用堆优化,很慢。
所以直接学习堆优化的。
学习笔记?度娘吧。没有空再写一遍啦。
所以直接上代码。第一个是带注释的,第二个是没有注释的。
模板。
P4779 【模板】单源最短路径(标准版)
1 #include <iostream> 2 #include <cstdio> 3 #include <vector> 4 #include <queue> 5 #define R register 6 #define MN 100005 7 #define INF 0x7fffffff 8 using namespace std; 9 int n,m,s;//n个点,m条边,起始点s 10 int d[MN];//起始点到i的最短距离 11 typedef pair<int ,int> p;//点对的第一个数i表示d[i],第二个数j表示这个点的编号 12 struct edge{int to,cost;};//结构体储存边的终点及权 13 vector <edge> G[MN];//每一个点及他的所有连点 14 inline int ri(){ 15 char c=getchar();int x=0,w=1; 16 while(!isdigit(c)){if(c=='-')w=-1;c=getchar();} 17 while( isdigit(c)){x=(x<<3)+(x<<1)+c-48;c=getchar();} 18 return x*w; 19 } 20 inline void dijstra(int s){ 21 priority_queue<p,vector<p>,greater<p> >que;//定义按照d[i]从小到大 22 fill(d+1,d+n+1,INF);//初始化所有的d为INF 23 d[s]=0;que.push(p(0,s));//源点到自己的距离为0,这个点入队 24 while(!que.empty()){//只要队列还不为空 25 p q=que.top();que.pop();//取出d[i] 26 int v=q.second;//v是这个点 27 if(d[v]<q.first)continue;//如果队列某点的d值大于目前的它的最优值,则跳过这个点 28 for(int i=0;i<G[v].size();i++){//遍历它的每个连点 29 edge e=G[v][i];//定义一个e,表示当前这个点的连边及终点 30 if(d[e.to]>d[v]+e.cost){//如果目前到终点的最短距离比从源点先到当前点的最短距离加上直接连边来的大 31 d[e.to]=d[v]+e.cost;//更新 32 que.push(p(d[e.to],e.to));//可入队 33 } 34 } 35 } 36 } 37 int main(){ 38 n=ri(),m=ri(),s=ri(); 39 int x,y,z; 40 for(R int i=1;i<=m;++i){ 41 x=ri(),y=ri(),z=ri();//输入x和y之间的有向边z 42 edge e={y,z};//定义一个e.. 43 G[x].push_back(e); //添加到邻接表x中 44 } 45 dijstra(s);//搜索源点 46 for(R int i=1;i<=n;i++)printf("%d ",d[i]);//输出 47 return 0; 48 }
1 #include <iostream> 2 #include <cstdio> 3 #include <vector> 4 #include <queue> 5 #define R register 6 #define MN 100005 7 #define INF 0x7fffffff 8 using namespace std; 9 int n,m,s; 10 int d[MN]; 11 typedef pair<int ,int> p; 12 struct edge{int to,cost;}; 13 vector <edge> G[MN]; 14 inline void dijstra(int s){ 15 priority_queue<p,vector<p>,greater<p> >que; 16 fill(d+1,d+n+1,INF); 17 d[s]=0;que.push(p(0,s)); 18 while(!que.empty()){ 19 p q=que.top();que.pop(); 20 int v=q.second; 21 if(d[v]<q.first)continue; 22 for(int i=0;i<G[v].size();i++){ 23 edge e=G[v][i]; 24 if(d[e.to]>d[v]+e.cost){ 25 d[e.to]=d[v]+e.cost; 26 que.push(p(d[e.to],e.to)); 27 } 28 } 29 } 30 } 31 inline int ri(){ 32 char c=getchar();int x=0,w=1; 33 while(!isdigit(c)){if(c=='-')w=-1;c=getchar();} 34 while( isdigit(c)){x=(x<<3)+(x<<1)+c-48;c=getchar();} 35 return x*w; 36 } 37 int main(){ 38 n=ri(),m=ri(),s=ri(); 39 int x,y,z; 40 for(R int i=1;i<=m;++i){ 41 x=ri(),y=ri(),z=ri(); 42 edge e={y,z}; 43 G[x].push_back(e); 44 } 45 dijstra(s); 46 for(R int i=1;i<=n;i++)printf("%d ",d[i]); 47 return 0; 48 }
2.Floyd算法
不过模板题了。
优化起来貌似是堆优化的dijkstra更快吧???
Floyd就是方便在它能求多组第i个点和第j个点的最短距离。
n^3。
放一道例题吧。
P1364 医院设置
1 #include<cstdio> 2 #include <iostream> 3 #define R register 4 #define INF 0x7fffffff 5 using namespace std; 6 int a[101],g[101][101]; 7 int n,ans=INF,tot; 8 inline int ri(){ 9 char c=getchar();int x=0,w=1; 10 while(!isdigit(c)){if(c=='-')w=-1;c=getchar();} 11 while( isdigit(c)){x=(x<<3)+(x<<1)+c-48;c=getchar();} 12 return x*w; 13 } 14 int main(){ 15 n=ri(); 16 for(R int i=1;i<=n;++i) 17 for(R int j=1;j<=n;++j) 18 g[i][j]=1000000; 19 for(R int i=1;i<=n;++i){ 20 int l,r; g[i][i]=0; 21 a[i]=ri(),l=ri(),r=ri(); 22 if(l)g[i][l]=g[l][i]=1; 23 if(r)g[i][r]=g[r][i]=1; 24 } 25 for(R int k=1;k<=n;++k) 26 for(R int i=1;i<=n;++i) 27 if(i!=k) 28 for(R int j=1;j<=n;++j) 29 if(i!=j&&k!=j&&g[i][k]+g[k][j]<g[i][j]) 30 g[i][j]=g[i][k]+g[k][j]; 31 for(R int i=1;i<=n;++i){ 32 tot=0; 33 for(R int j=1;j<=n;++j)tot+=g[i][j]*a[j]; 34 ans=min(ans,tot); 35 } 36 printf("%d",ans); 37 return 0; 38 }