图论,最短路,堆优化迪杰斯特拉,SPFA

学习了迪杰斯特拉.

类似贪心.

也有点像弗洛伊德.

上代码.

这种是规定了起始节点为1的.

 1 #include <cstdio>
 2 #include <iostream>
 3 #include <string>
 4 #include <bits/stdc++.h>
 5 
 6 using namespace std;
 7 #define MAXN 10001
 8 #define MAXM 100001
 9 
10 //n点m边 
11 
12 struct edge{
13     int v;
14     int w;
15     int nxt;
16 }e[MAXM];
17 int head[MAXN];
18 int cnt;
19 
20 void addedge(int x,int y,int z) {
21     e[++cnt].v=y;
22     e[cnt].w=z;//边权 
23     e[cnt].nxt=head[x];
24     head[x]=cnt;
25 }
26 int dist[MAXN];
27 bool vis[MAXN];
28 priority_queue< pair<int,int> > q;
29 //第一维是dist相反数,这是大根堆
30 //第二维是节点编号 
31 int n,m;
32 
33 
34 void dijkstra () {
35     memset(dist,0x3f,sizeof(dist));
36     memset(vis,0,sizeof(vis));
37     dist[1]=0;
38     q.push(make_pair(0,1));
39     while (q.size()) {
40         int x=q.top().second;
41         q.pop();
42         if (vis[x]) continue;
43         vis[x]=1;
44         for (int i=head[x];i;i=e[i].nxt) {
45             int y=e[i].v;
46             int z=e[i].w;
47             if (dist[y]>dist[x]+z) {
48                 dist[y]=dist[x]+z;
49                 q.push(make_pair(-dist[y],y));
50             }
51         } 
52     }
53 }
54 
55 int main () {
56     cin>>n>>m;
57     for (int i=1;i<=m;i++) {
58         int x,y,z;
59         cin>>x>>y>>z;
60         addedge(x,y,z);
61         //addedge(y,x,z);
62     }
63     dijkstra();
64     for (int i=1;i<=n;i++) {
65         cout<<dist[i]<<" ";
66     }
67     return 0;
68 }
69 
70 /*
71 5 8
72 1 2 2
73 1 3 1
74 1 5 4
75 2 3 6
76 2 4 3
77 2 5 4
78 4 5 5
79 3 5 2
80 */

 其实迪杰斯特拉还可以是有起点的,

自己可以定起点,

下面就是,

这就是单元最短路,

 1 #include <cstdio>
 2 #include <iostream>
 3 #include <string>
 4 #include <bits/stdc++.h>
 5 
 6 using namespace std;
 7 #define MAXN 10001
 8 #define MAXM 100001
 9 
10 //n点m边
11 
12 struct edge {
13     int v;
14     int w;
15     int nxt;
16 } e[MAXM];
17 int head[MAXN];
18 int cnt;
19 
20 void addedge(int x,int y,int z) {
21     e[++cnt].v=y;
22     e[cnt].w=z;//边权
23     e[cnt].nxt=head[x];
24     head[x]=cnt;
25 }
26 int dist[MAXN];
27 bool vis[MAXN];
28 priority_queue< pair<int,int> > q;
29 //第一维是dist相反数,这是大根堆
30 //第二维是节点编号
31 int n,m;
32 
33 
34 void dijkstra (int st) {
35     memset(dist,0x3f,sizeof(dist));
36     memset(vis,0,sizeof(vis));
37     dist[st]=0;
38     q.push(make_pair(0,st));
39     while (q.size()) {
40         int x=q.top().second;
41         q.pop();
42         if (vis[x]) continue;
43         vis[x]=1;
44         for (int i=head[x]; i; i=e[i].nxt) {
45             int y=e[i].v;
46             int z=e[i].w;
47             if (dist[y]>dist[x]+z) {
48                 dist[y]=dist[x]+z;
49                 q.push(make_pair(-dist[y],y));
50             }
51         }
52     }
53 }
54 
55 int main () {
56     cin>>n>>m;
57     for (int i=1; i<=m; i++) {
58         int x,y,z;
59         cin>>x>>y>>z;
60         addedge(x,y,z);
61         //addedge(y,x,z);
62     }
63     for (int i=1; i<=n; i++) {
64         dijkstra(i);
65         cout<<""<<i<<"为起点"<<endl; 
66         for (int i=1; i<=n; i++) {
67             cout<<dist[i]<<" ";
68         }
69         cout<<endl;
70         cout<<endl;
71     }
72 
73 
74     return 0;
75 }
76 
77 /*
78 5 8
79 1 2 2
80 1 3 1
81 1 5 4
82 2 3 6
83 2 4 3
84 2 5 4
85 4 5 5
86 3 5 2
87 */

 下面还有SPFA,

稀疏图上效率很高,

这是以1为起点的,

#include <cstdio>
#include <iostream>
#include <string>
#include <bits/stdc++.h>

using namespace std;
#define MAXN 10001
#define MAXM 100001

//n点m边 

struct edge{
    int v;
    int w;
    int nxt;
}e[MAXM];
int head[MAXN];
int cnt;

void addedge(int x,int y,int z) {
    e[++cnt].v=y;
    e[cnt].w=z;//边权 
    e[cnt].nxt=head[x];
    head[x]=cnt;
}
int dist[MAXN];
bool vis[MAXN];
queue <int> q;
int n,m;


void spfa () {
    memset(dist,0x3f,sizeof(dist));
    memset(vis,0,sizeof(vis));
    dist[1]=0;
    vis[1]=1;
    q.push(1);
    while (q.size()) {
        int x=q.front();
        q.pop();
        vis[x]=0;
        for (int i=head[x];i;i=e[i].nxt) {
            int y=e[i].v;
            int z=e[i].w;
            if (dist[y]>dist[x]+z) {
                dist[y]=dist[x]+z;
                if (!vis[y]) {
                    q.push(y);
                    vis[y]=1;
                }
            }
        } 
    }
}

int main () {
    cin>>n>>m;
    for (int i=1;i<=m;i++) {
        int x,y,z;
        cin>>x>>y>>z;
        addedge(x,y,z);
        //addedge(y,x,z);
    }
    spfa();
    for (int i=1;i<=n;i++) {
        cout<<dist[i]<<" ";
    }
    return 0;
}

/*
5 8
1 2 2
1 3 1
1 5 4
2 3 6
2 4 3
2 5 4
4 5 5
3 5 2
*/

再看看以任意节点为起点的,

 这下就全了

#include <cstdio>
#include <iostream>
#include <string>
#include <bits/stdc++.h>

using namespace std;
#define MAXN 10001
#define MAXM 100001

//n点m边

struct edge {
    int v;
    int w;
    int nxt;
} e[MAXM];
int head[MAXN];
int cnt;

void addedge(int x,int y,int z) {
    e[++cnt].v=y;
    e[cnt].w=z;//边权
    e[cnt].nxt=head[x];
    head[x]=cnt;
}
int dist[MAXN];
bool vis[MAXN];
queue <int> q;
int n,m;


void spfa (int st) {
    memset(dist,0x3f,sizeof(dist));
    memset(vis,0,sizeof(vis));
    dist[st]=0;
    vis[st]=1;
    q.push(st);
    while (q.size()) {
        int x=q.front();
        q.pop();
        vis[x]=0;
        for (int i=head[x]; i; i=e[i].nxt) {
            int y=e[i].v;
            int z=e[i].w;
            if (dist[y]>dist[x]+z) {
                dist[y]=dist[x]+z;
                if (!vis[y]) {
                    q.push(y);
                    vis[y]=1;
                }
            }
        }
    }
}

int main () {
    cin>>n>>m;
    for (int i=1; i<=m; i++) {
        int x,y,z;
        cin>>x>>y>>z;
        addedge(x,y,z);
        //addedge(y,x,z);
    }
    for (int i=1; i<=n; i++) {
        spfa(i);
        cout<<""<<i<<"为起点"<<endl; 
        for (int i=1; i<=n; i++) {
            cout<<dist[i]<<" ";
        }
        cout<<endl;
        cout<<endl;
    }


    return 0;
}

/*
5 8
1 2 2
1 3 1
1 5 4
2 3 6
2 4 3
2 5 4
4 5 5
3 5 2
*/

 

posted @ 2018-10-11 23:03  codemaker_li  阅读(363)  评论(0编辑  收藏  举报