数据结构研究之十一 高等图算法

1.所有点对间的最短路径
a.定义:指以图G=(V,E)为对象,求G中每两点之间最短距离的问题
b.核心:关键在于判断在经过中间点与不经过中间点之间的两者距离的最小值,可用弗洛伊德算法求解
c.代码:

//
// Created by 叶子 on 2018/2/6.
// 使用弗洛伊德算法计算所有点对间的最短路径
//

#include "iostream"
#include "algorithm"
#include "vector"
#include "climits"
using namespace std;

static const int MAX = 100;
static const long long INFTY = ( 1LL < 32);

int n;
long long d[MAX][MAX];

void floyd(){
    for (int k = 0 ; k < n ; k ++){
        for ( int i = 0 ; i < n ; i ++){
            if ( d[i][k] == INFTY) continue;
            for ( int j = 0 ; j < n ; j ++){
                if ( d[k][j] == INFTY ) continue;
                d[i][j] = min(d[i][j],d[i][k] + d[k][j]);
            }
        }
    }
}

int main(){
    int e,u,v,c;
    cin >> n >> e;

    for ( int i = 0 ; i < n ; i ++){
        for ( int j = 0 ; j < n ; j ++){
            d[i][j] = (( i == j ) ? 0 : INFTY);
        }
    }

    for ( int i = 0 ; i < e ; i ++){
        cin >> u >> v >> c;
        d[u][v] = c;
    }

    floyd();

    bool negative = false;
    for ( int i = 0 ; i < n ; i ++) if ( d[i][i] < 0 ) negative = true;

    if ( negative ){
        cout << "NEGATIVE CYCLE" << endl;
    }else{
        for ( int i = 0 ; i < n ; i ++){
            for ( int j = 0 ; j < n ; j ++){
                if ( j ) cout << " ";
                if ( d[i][j] == INFTY ) cout << "INF";
                else cout << d[i][j];
            }
            cout <<endl;
        }
    }

    return 0;
}

2.拓朴排序:
a.题目:求输出对给定DAG G进行拓朴排序后的顶点顺序
b.核心算法:用深度优先搜索或者广度优先搜索就能实现拓朴排序
c.代码:
//
// Created by 叶子 on 2018/2/6.
// 广度优先搜索的拓朴排序
//

#include "iostream"
#include "vector"
#include "queue"
#include "list"
using namespace std;
static const int MAX = 100000;

vector<int> G[MAX];
list<int> out;
bool V[MAX];
int N;
int indeg[MAX];

void bfs(int s){
    queue<int> q;
    q.push(s);
    V[s] = true;
    while ( !q.empty()){
        int u = q.front();
        q.pop();
        out.push_back(u);
        for ( int i = 0 ; i < G[u].size() ; i ++){
            int v = G[u][i];
            indeg[v]--;
            if ( indeg[v] == 0 && !V[v]){
                V[v] = true;
                q.push(v);
            }
        }
    }
}

void tsort(){
    for ( int i = 0; i < N ; i ++){
        indeg[i] = 0;
    }

    for ( int u = 0 ; u < N ; u ++){
        for ( int i = 0 ; i < G[u].size() ; i ++){
            int v = G[u][i];
            indeg[v]++;
        }
    }

    for ( int u = 0 ; u < N ; u ++){
        if ( indeg[u] == 0 && !V[u] ) bfs(u);
    }

    for ( list<int>::iterator it = out.begin(); it != out.end() ; it ++){
        cout << *it << endl;
    }
}

int main(){
    int s,t,M;

    cin >> N >> M;

    for ( int i = 0 ; i < N ; i ++) V[i] = false;

    for ( int i = 0 ; i < M ; i ++){
        cin >> s >> t;
        G[s].push_back(t);
    }

    tsort();

    return 0;
}
3.树的直径:
a.题目:求权值非负的无向树T的直径,即求此树最远结点间的距离。
b.核心:任意在图中选一节点,求此节点到此图两边界间的距离。
c.代码:
//
// Created by 叶子 on 2018/2/6.
// 用深度优先搜索求树的直径
//

#include "iostream"
#include "queue"
using namespace std;
const int MAX = 100000;
const int INFTY = ( 1 << 30);

class Edge{
public:
    int t,w;
    Edge(){}
    Edge(int t,int w) : t(t),w(w) {}
};

vector<Edge> G[MAX];
int n,d[MAX];

void bfs(int s){
    for (int i = 0 ; i < n ; i ++) d[i] = INFTY;
    queue<int> Q;
    Q.push(s);
    d[s] = 0;
    int u;
    while ( !Q.empty()){
        u = Q.front();
        Q.pop();
        for ( int i = 0 ; i < G[u].size(); i ++){
            Edge e = G[u][i];
            if ( d[e.t] == INFTY ){
                d[e.t] = d[u] + e.w;
                Q.push(e.t);
            }
        }
    }
}

void solve(){
    bfs(0);
    int maxv = 0;
    int tgt = 0;
    for ( int i = 0 ; i < n ; i ++){
        if ( d[i] == INFTY ) continue;
        if ( maxv < d[i] ){
            maxv = d[i];
            tgt = i;
        }
    }

    bfs(tgt);
    maxv = 0;
    for ( int i = 0 ; i < n ; i ++){
        if ( d[i] == INFTY ) continue;
        maxv = max(maxv,d[i]);
    }

    cout << maxv << endl;
}

int main(){
    int s,t,w;
    cin >> n;

    for ( int i = 0 ; i < n - 1 ; i ++){
        cin >> s >> t >> w;

        G[s].push_back(Edge(t,w));
        G[t].push_back(Edge(s,w));
    }
    solve();
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值