图论总结

这是一个图论总结。

建图

邻接矩阵

用一个二维数组表示两个点之间有没有连边

s[x][y] = dis; //x和y之间有一条长度为dis的边

邻接表

用一个结构体记录所有的边,同时保存以这条边为起点的上一条边的编号,然后保存所有起点的最后一条边即可。

struct Edge{
    int next, to, dis;
}e[MAXN * MAXN];
int head[MAXN], num;
inline void Add(int from, int to, int dis){
    e[++num].to = to;
    e[num].dis = dis;
    e[num].next = head[from];
    head[from] = num;
}

最短路

单源最短路

Dijkstra

创建一个队列,保存“已经确定最短路”的点的集合。初始时队列里只有源点,除源点外所有点的距离赋值正无穷。
当集合不为空时,取出集合内距离最短的一个点,移除集合,枚举这个点连的所有边,如果这个点的距离加上这条边的距离比到的那个点小,那么更新这条边到的那个点的距离,并把它加入集合。重复执行。

//洛谷 P4779 【模板】单源最短路径(标准版)
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <queue>
using namespace std;
inline int read(){
    int s = 0, w = 1;
    char ch = getchar();
    while(ch < '0' || ch > '9'){if(ch == '-')w = -1;ch = getchar();}
    while(ch >= '0' && ch <= '9') s = s * 10 + ch - '0',ch = getchar();
    return s * w;
}
const int MAXN = 100010;
const int MAXM = 200010; 
struct Node{
    int next, to, dis;
}e[MAXM];
int head[MAXN], num;
ll dis[MAXN];
bool v[MAXN];
void Add(int from, int to, int dis){
    e[++num].to = to;
    e[num].next = head[from];
    e[num].dis = dis;
    head[from] = num;
}
int n, m, s;
int a, b, c;
struct cmp{
    bool operator () (int a, int b){
        return dis[a] > dis[b];
    }
};
priority_queue <int, vector<int>, cmp> q;
int main(){
    n = read(); m = read(); s = read();
    for(i = 1; i <= m; ++i) a = read(), b = read(), c = read(), Add(a, b, c);
    for(i = 1; i <= n; ++i) dis[i] = INF;
    dis[s] = 0;
    q.push(s);
    while(!q.empty()){
      int now = q.top();
      q.pop();
      if(v[now]) continue;
      v[now] = true;
      for(int i = head[now];i;i = e[i].next){
         if(!v[e[i].to] && dis[e[i].to] > dis[now] + e[i].dis)
           dis[e[i].to] = dis[now] + e[i].dis, q.push(e[i].to);
      }
    }
    for(i = 1; i <= n; ++i) printf("%lld ", dis[i]);
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/Qihoo360/p/9614159.html
今日推荐