[SinGuLaRiTy-1001] Calculation Of The Shortest Path 最短路算法集锦

来源:互联网 发布:兰州ps软件班 编辑:程序博客网 时间:2024/05/21 15:57
 By Wen Jian
A Calculation Of The Shortest Path Codes Library.

Sources from CQBZ Judge & CODE[VS] [Codevs Website][CQBZ Judge]
最短路算法代码库。

Includes Dijkstra , SPAF , Floyd , BellmanFord.
包含 Dijkstra , SPAF , Floyd , BellmanFord 。

[ Dijkstra ]

Subject: First line: two numbers that describe the number of points and edges; Then the following lines of data describe the start , end , value of every edge; Last line: two numbers : Start , End;

Original Subject: [CQBZOJ 1172]

题目描述

有向图的单源点最短路问题(Dijkstra算法)

输入

第1行:2个空格分开的整数n(2<=n<=500)和m(10<=m<=20000),分别表示图的顶点数和边数。

第2..m+1行:每行3个空格分开的整数i,j, w。i表示一条边的起点,j表示终点, w表示权值。

第m+2行:2个整数s,t(1<=s,t<=n),表示指定的顶点。

输出

第1行:最小距离

第2行:最短路径(从起点到终点的序列,用1个空格分开)

样例输入

5 7
1 2 10
1 4 30
1 5 100
2 3 50
3 5 10
4 3 20
4 5 60
1 5

样例输出

60
1 4 3 5

#include<iostream>#include<cstring>#include<cstdlib>#include<cstdio>#include<cmath>using namespace std;int n,m;int G[501][501],dis[501],L[501];bool used[501];void Dijkstra(int s){    for(int i=1;i<=n;i++)    {        used[s]=1;        for(int j=1;j<=n;j++)        {            if(G[s][j]==0||s==j)                continue;            if(dis[j]>dis[s]+G[s][j])                dis[j]=dis[s]+G[s][j],L[j]=s;        }        int themin=0x3f3f3f3f;        for(int i=1;i<=n;i++)                            if(used[i]==0&&dis[i]<themin)                s=i,themin=dis[i];    }}int main(){    int a,b,c,S,E,cnt=1;    scanf("%d%d",&n,&m);    for(int i=1;i<=m;i++)    {        scanf("%d%d%d",&a,&b,&c);        G[a][b]=c;    }    scanf("%d%d",&S,&E);    int e=E;    dis[S]=0;    for(int i=1;i<=n;i++)        if(i!=S) dis[i]=0x3f3f3f3f;                    Dijkstra(S);          printf("%d\n",dis[E]);    while(L[E]!=0)    {        dis[cnt++]=L[E];        E=L[E];    }    for(int i=cnt-1;i>=1;i--)        printf("%d ",dis[i]);    printf("%d",e);    return 0;}

[ SPAF ]

Subject: First line: two numbers that describe the number of points and edges; Then the following lines of data describe the start , end , value of every edge. Output the shortest path between point[1] and point[n].

Original Subject: [CQBZOJ 1178]

题目描述

有向图的单源点最短路径问题。源点编号为1,终点编号为n。

输入

第1行:2个空格分开的整数n(2<=n<=5000)和m(10<=m<=500000),分别表示图的顶点数和边数。

第2..m+1行:每行3个空格分开的整数i,j, w。i表示一条边的起点,j表示终点, w表示权值。

输出

第1行:1个整数,表示最小距离

样例输入

样例1:
4 7
1 2 68
1 3 19
1 4 66
2 3 23
3 4 65
3 2 57
4 1 68

样例2:
3 3
1 2 -7
2 3 4
3 1 2

样例输出

样例1:
66
样例2:
No Solution

#include<iostream>#include<cstdio>#include<cstring>#include<queue>using namespace std;struct node{    int v,w,next;}edge[500050];int cnt,head[5050],n,m,dis[5050],tot[5050];bool inq[5050];void addedge(int u,int v,int w){    edge[cnt].v=v;    edge[cnt].w=w;    edge[cnt].next=head[u];    head[u]=cnt++;}bool SPFA(){    memset(dis,0x3f,sizeof dis);    dis[1]=0;    inq[1]=1;    deque<int>q;    q.push_front(1);    while(!q.empty())    {        int u=q.front();        q.pop_front();        inq[u]=0;        for(int i=head[u];i!=-1;i=edge[i].next)        {            int v=edge[i].v,w=edge[i].w;            if(dis[v]>dis[u]+w)            {                dis[v]=dis[u]+w;                if(!inq[v])                {                    if(dis[v]<dis[u])q.push_front(v);                    else q.push_back(v);                    inq[v]=1;                    if(++tot[v]>n)return 0;                }            }        }    }    return 1;}int main(){    int u,v,w;    scanf("%d%d",&n,&m);    memset(head,-1,sizeof head);    for(int i=1;i<=m;++i)    {        scanf("%d%d%d",&u,&v,&w);        addedge(u,v,w);    }    SPFA()?printf("%d\n",dis[n]):    puts("No Solution");}

[Floyd]

Subject:(None)

Original Subject:(None)

#include <stdio.h>  #include <string.h>  #define maxn 100  #define INF -1  int map[maxn][maxn];  int n, m, path[maxn][maxn];    void Floyd(int n)  {      int i, j, k;      for(k = 0; k < n; ++k)          for(i = 0; i < n; ++i)              for(j = 0; j < n; ++j)                  if(map[i][k] != INF && map[k][j] != INF && (map[i][k] + map[k][j] < map[i][j] || map[i][j] == INF)){                      map[i][j] = map[i][k] + map[k][j];                      path[i][j] = k;                  }             }    void getPath(int v, int u)  {      int k = path[v][u];      if(k == INF){          printf("%d===>", v);                  return;      }      getPath(v, k);      getPath(k, u);  }    int main()  {       scanf("%d%d", &n, &m);      memset(map, INF, sizeof(map));      memset(path, INF, sizeof(path));      int i, j, a, b, c;      for(i = 0; i < n; ++i) map[i][i] = 0;      for(i = 0; i < m; ++i){          scanf("%d%d%d", &a, &b, &c);          map[a][b] = c;      }      Floyd(n);      for(i = 0; i < n; ++i)          for(j = 0; j < n; ++j)              if(map[i][j] != INF){                  printf("%d->%d:%d\n the path is:", i, j, map[i][j]);                  getPath(i, j);                  printf("%d\n", j);              }      return 0;  }  

[BellmanFord]

Subject: First line: two numbers that describe the number of points and edges; Then the following lines of data describe the start , end , value of every edge; Last line: two numbers : Start , End;

Original Subject: [CQBZOJ 2890]

题目描述

有向图负权的单源点最短路问题(BellmanFord 算法)

输入

第1行:2个空格分开的整数n(2<=n<=500)和m(10<=m<=20000),分别表示图的顶点数和边数。

第2..m+1行:每行3个空格分开的整数i,j, w。i表示一条边的起点,j表示终点, w表示权值。

第m+2行:2个整数s,t(1<=s,t<=n),表示指定的顶点。

输出

第1行:最小距离

第2行:最短路径(从起点到终点的序列,用1个空格分开)

如果出现负权回路,输出:No Solution

样例输入

样例1:
6 7
1 2 2
1 3 -1
2 4 -3
3 4 3
3 6 7
4 6 -2
3 5 6
1 6

样例2:
3 3
1 2 -7
2 3 4
3 1 2
1 3

样例输出

样例1:
-3
1 2 4 6

样例2:
No Solution

提示

如果最短路径有多条,输出路径经过边数较小的解; 如果最短路径边数相同,输出编号较小的序列.



#include<cstdio> #include<cstring> #include<algorithm> using namespace std; int f[20005][3],dis[505],s[505]; void print(int x){    if(s[x]==0) return;    print(s[x]);    printf(" %d",x);}int main() {    int n,m,i,j,q,z;     scanf("%d%d",&n,&m);     for(i=1;i<=m;i++)        scanf("%d%d%d",&f[i][0],&f[i][1],&f[i][2]);     scanf("%d%d",&q,&z);    memset(dis,1,sizeof(dis));     dis[q]=0;    for(i=1;i<=n;i++){        for(j=1;j<=m;j++){            if(dis[f[j][0]]+f[j][2]<dis[f[j][1]]&&i<n){                dis[f[j][1]]=dis[f[j][0]]+f[j][2];                s[f[j][1]]=f[j][0];            }            if(i==n&&dis[f[j][0]]+f[j][2]<dis[f[j][1]]){                printf("No Solution");                return 0;            }        }    }    printf("%d\n",dis[z]);     printf("%d",q);     print(z);}

Coding by SinGuLaRiTy

Time : 2017-02-03



1 0
原创粉丝点击