算法-图

简单的图

1.可能到达所有点的衔接

class Solution {
public:
    vector<int> findSmallestSetOfVertices(int n, vector<vector<int>>& edges) {
        vector<int> temp(n + 1, 0);
        for(int i = 0; i < edges.size(); ++ i ) { ++ temp [[ i ] [ 1 ] ] ; }        向量< int > res ; forint i = 0 ; i < n ; ++ i ){ if ( temp [ i ] == 0 ) res 。emplace_back (我); }返回
            
        

            
                
        
        资源; } } ; ```
    



## 2.所有可能的路径```的cpp类解{公共:    矢量<矢量< INT >> allPathsSourceTarget (矢量<矢量< INT >> &图表){ INT ñ =曲线图。大小();         矢量<矢量< INT > >水库;         向量< int >路径{ 0


  

  
        
 
};
        bfs(0, n - 1, path, res, graph);
        return res;
    }
    void bfs(int cur, int end, vector<int> &path, vector<vector<int> > &res, vector<vector<int> > &graph) {
        if (cur == end) {
            res.emplace_back(path);
            return ;
        }
        for (auto i : graph[cur]) {
            path.emplace_back(i);
            bfs(i, end, path, res, graph);
            path.pop_back();
        }
        return ;
    }
};

3.克隆图

dfs

class Solution {
public:
    unordered_map<Node *, Node *> visited;
    Node* cloneGraph(Node* node) {
        if(node == nullptr)  return node;
        if (visited.find(node) !=  visited.end()) {
            return visited[node];
        }
        Node *cloneNode = new Node(node->val);
        visited[node] = cloneNode;
        for (auto &neigh: node->neighbors) {
            cloneNode->neighbors.emplace_back(cloneGraph(neigh));
        }
        return cloneNode;
    }
};

bfs

class Solution {
public:
    Node* cloneGraph(Node* node) {
        if(node == nullptr) return node;
        unordered_map<Node *, Node *> visited;
        visited[node] = new Node(node->val);
        queue<Node *> que;
        que.emplace(node);
        while(!que.empty()) {
            Node *cur = que.front();
            que.pop();
            for (auto &neigh: cur->neighbors) {
                if (visited.find(neigh) == visited.end()) {
                    visited[neigh] = new Node(neigh->val);
                    que.emplace(neigh);
                }
                visited[cur]->neighbors.emplace_back(visited[neigh]);
            }
        }
        return visited[node];
    }
};

4.冗余连接

class Solution {
public:
    vector<int> findRedundantConnection(vector<vector<int>>& edges) {
        int n = edges.size();
        vector<int> fa(n + 5, 0);
        init(fa, n);
        for (auto e : edges) {
            int a = e[0], b = e[1];
            if (get(fa, a) != get(fa, b)) {
                merge(fa, a, b);
            } else {
                return e;
            }
        }
        return vector<int> {};
    }

    void init(vector<int> &fa, int n) {
        for (int i = 1; i <= n; i++) {
            fa[i] = i;
        }
    } 
    int get(vector<int> &fa, int x) {
        return fa[x] = (x - fa[x]) ? get(fa, fa[x]) : x;
    }

    void merge(vector<int> &fa, int a, int b) {
        fa[get(fa, a)] = get(fa, b);
    }
};

6.钥匙和房间

bfs

class Solution {
public:
    bool canVisitAllRooms(vector<vector<int>>& rooms) {
        int n = rooms.size();
        vector<int> visited(n + 5, 0);
        visited[0] = 1;
        queue<int> que;
        que.emplace(0);
        int sum = 1;
        while(!que.empty()) {
            int cur = que.front();
            que.pop();
            for (auto key : rooms[cur]) {
                if (visited[key] == 0) {
                    sum += 1;
                    visited[key] = 1;
                    que.emplace(key);
                }
            }
        }
        return sum == n;

    }
};

dfs

class Solution {
public:
    bool canVisitAllRooms(vector<vector<int>>& rooms) {
        int n = rooms.size();
        vector<int> visited(n, 0);
        int visit_num = 0;
        dfs(rooms, 0, visited, visit_num);
        return visit_num == n;
    }
 
    void dfs(vector<vector<int> >& rooms, int cur, vector<int> &visited, int &visit_num) {
        visited[cur] = 1;
        visit_num += 1;
        for (auto key : rooms[cur]) {
            if (visited[key] == 0) {
                dfs(rooms, key, visited, visit_num);
            }
        }        
    }
};

7.统计参与通信的服务器

class Solution {
public:
    int countServers(vector<vector<int>>& grid) {
        int n = grid.size(), m = grid[0].size();
        vector<int> every_line_num(n + 1, 0);
        vector<int> every_column_num(m + 1, 0);
        for (int i = 0; i < n; ++i) {
            for (int j = 0; j < m; ++j) {
                if (grid[i][j] == 1) {
                    ++every_line_num[i];
                    ++every_column_num[j];
                }
            }
        }
        int sum = 0;
        for(int i = 0; i < n; ++i) {
            for (int j = 0; j < m; ++j) {
                if (grid[i][j] == 1 && (every_line_num[i] > 1 || every_column_num[j] > 1)) {
                    ++sum;
                }
            }
        }
        return sum;
    }
};

最短路径

五大算法的时间复杂度

在这里插入图片描述

1.floyd

公式
已知起点和终点.
节点数n个, 中转点i, 起点j, 终点k
dir[x][y]是指从x到y的最短路径
求最短路
缺点慢还耗内存

for (int i = 0; i < n; i++) {
	for (int j = 0; j < n; j++) {
		for (int k = 0; k < n; k++) {
			dir[j][k] = max(dir[j][k], dir[j][i] + dir[i][k]);		
		}	
	}
}
include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdio>
#include<queue>
#include<vector>
#include<climits>
using namespace std;
 
const int MAX_N = 100;

void floyd(int n, vector<vector<int> >& dir) {
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            for (int k = 0; k < n; k++) {
                dir[j][k] = max(dir[j][k], dir[j][i] + dir[i][k]);
            }
        }
    }
    return ;
}

int main() {
    int node_num, dir_num, star_node;
    cin >> node_num >> dir_num >> star_node;
    vector<vector<int> > dir(MAX_N + 5, vector<int>(MAX_N + 5, INT_MAX));

    for (int i = 0; i < dir_num; i++) {//自己到自己
        dir[i][i] = 0;
    }

    for (int i = 0; i < dir_num; i++) {
        int s, e, l;
        cin >> s >> e >> l;
        dir[s][e] = min(dir[s][e], l);
    }
    
    for (int i = 0; i <= node_num; i++) {
        if (i != 1) {
            cout << " ";
        }
        if (dir[star_node][i] == 0x3F3F3F3F) {//路不通
            cout << -1;
        } else {
            cout << dir[star_node][i];
        }
    }
    return 0;
}

链式前向星

head[x]: 以x为起点的最后一条边的编号
struct edg{
int e, dist, next;//e:终点, dist权值, next: 同一个起点的上一条边的编号
};

我们可以通过last_edg = head[x]来查找访问节点x的最后一条边,在通过edg[last_edg] 来查找与last_edg访问同一节点的边,直到出现负边,表示访问该节点的边已经遍历完.

#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdio>
#include<queue>
#include<vector>
using namespace std;
 
struct edge{
    int e, dist, next;
};

class Graph{
public:
    Graph(int nodeNum, int edgNum): nodeNum(nodeNum), edgNum(edgNum){
        head = vector<int>(nodeNum, -1);
        edg = vector<edge>(edgNum); 
    }
    void cfs(int edg_number, int sta, int end, int len) {
        edg[edg_number].e = end;
        edg[edg_number].dist = len;
        edg[edg_number].next = head[sta];
        head[sta] = edg_number;
    }
    void printGraphList() {
        for (int i = 1; i <= nodeNum; i++) {
            cout << i << " :";
            for (int j = head[i]; j != -1; j = edg[j].next) {
                int e = edg[j].e, d = edg[j].dist;
                cout << "(" << e << " " << d << ") ";
            }
            cout << endl;
        }
    }
    ~Graph() {
        head.clear();
        edg.clear();
    } 
private:
    int nodeNum, edgNum;
    vector<int> head;
    vector<edge> edg;  
};

int main() {
    int n, m, s;
    cin >> n >> m >> s;
    Graph g(n, m);
    for (int i = 0; i < m; i++) {
        int a, b, c;
        cin >> a >> b >> c;
        g.cfs(i, a, b, c);
    }
    g.printGraphList();
    return 0;
}

2.dijkstra

缺点是不能有负边, 且单元, 起点固定, 只有一个起点

已知一固定起点,终点未知.

#include <iostream>
#include <queue>
#include <cstring>
using namespace std;

struct node {
    int now, dist;
    bool operator< (const node &b) const {
        return this->dist > b.dist;
    }
};

int n, m, s, arr[1005][1005], ans[1005];

int main() {
    memset(arr, 0x3F, sizeof(arr));
    memset(ans, 0x3F, sizeof(ans));
    cin >> n >> m >> s;
    for (int i = 0; i < m; i++) {
        int a, b, c;
        cin >> a >> b >> c;
        arr[a][b] = min(arr[a][b], c);
    }
    priority_queue<node> que;
    que.push((node){s, 0});
    while (!que.empty()) {
        node temp = que.top();
        que.pop();
        if (ans[temp.now] != 0x3F3F3F3F) {
            continue;
        }
        ans[temp.now] = temp.dist;
        for (int i = 1; i <= n; i++) {
            if (arr[temp.now][i] != 0x3F3F3F3F) {
                que.push((node){i, temp.dist + arr[temp.now][i]});
            }
        }
    }
    for (int i = 1; i <= n; i++) {
        if (i != 1) {
            cout << " ";
        }
        if (ans[i] == 0x3F3F3F3F) {
            cout << -1;
        } else {
            cout << ans[i];
        }
    }
    cout << endl;
    return 0;
}

3.优化的dijkstra(链式前向星+dijkstra)

#include<iostream>
#include<queue>
#include<vector>
#include <climits>
using namespace std;
 
struct edge{
    int e, dist, next;
};

class Graph{
public:
    Graph() = default;
    Graph(int nodenum, int edgNum): __nodeNum(nodenum), edgNum(edgNum){
        head = vector<int>(nodenum, -1);
        edg = vector<edge>(edgNum); 
    }

    int nodeNum() {
        return __nodeNum;
    }
    void cfs(int edg_number, int sta, int end, int len) {
        edg[edg_number].e = end;
        edg[edg_number].dist = len;
        edg[edg_number].next = head[sta];
        head[sta] = edg_number;
        return ;
    }

    int edgend(int x) {
        return edg[x].e;
    }
    int edgdist(int x) {
        return edg[x].dist;
    }
    int edgnext(int x) {
        return edg[x].next;
    }

    int lastedg(int x) {
        return head[x];
    }
    void printGraphList() {
        for (int i = 1; i <= __nodeNum; i++) {
            cout << i << " :";
            for (int j = head[i]; j != -1; j = edg[j].next) {
                int e = edg[j].e, d = edg[j].dist;
                cout << "(" << e << " " << d << ") ";
            }
            cout << endl;
        }
        return ;
    }
    ~Graph() {
        head.clear();
        edg.clear();
    }
private:
    int __nodeNum, edgNum;
    vector<int> head;
    vector<edge> edg;  
};


struct node{
    int now, dist;
    bool operator< (const node &b)  const{
       return this->dist > b.dist;
    }
};

class MinPath{
public:
    MinPath(Graph g, int sta):g(g), sta(sta){
        minpaths = vector<int>(g.nodeNum() + 1, INT_MAX);
    }
    void dijkstra() {
        que.push((node){sta, 0});
        while(!que.empty()) {
            node temp = que.top();
            que.pop(); 
            if (minpaths[temp.now] > temp.dist) minpaths[temp.now] = temp.dist;
            else continue;
            for (int i = g.lastedg(temp.now); i != -1; i = g.edgnext(i)) {
                int e = g.edgend(i), d = g.edgdist(i);
                if (minpaths[e] > minpaths[temp.now] + d) {
                    que.push((node){e, minpaths[temp.now] + d});                
                }
                    
            }      
        }
        return ;
    }

    void printMinPath() {
        for (int i = 1; i <= g.nodeNum(); i++) {
            if (i != 1) {
                cout << " ";        
            }
            if (minpaths[i] == 0x3F3F3F3F) {
                cout << -1;                    
            } else {
                cout << minpaths[i];
            }
        }
        cout << endl;
    }
    int minpath(int t) {
        return minpaths[t];
    }
private:
    int sta;
    priority_queue<node> que;
    Graph g;
    vector<int> minpaths;
};

int main() {
    int n, m, s, t;
    cin >> n >> m >> s;
    Graph g(n, m);
    for (int i = 0; i < m; i++) {
        int a, b, c;
        cin >> a >> b >> c;
        g.cfs(i, a, b, c);
    }
    MinPath p(g, s);
    p.dijkstra();
    p.printMinPath();
    /*while(cin >> t) {
        cout << p.minpath(t) << endl;
    }
    */
    return 0;
}

4.bellman-ford

#include<iostream>
#include<queue>
#include<vector>
#include <climits>
using namespace std;
 
struct edge{
    int e, dist, next;
};

class Graph{
public:
    Graph() = default;
    Graph(int nodenum, int edgNum): __nodeNum(nodenum), edgNum(edgNum){
        head = vector<int>(nodenum, -1);
        edg = vector<edge>(edgNum); 
    }

    int nodeNum() {
        return __nodeNum;
    }
    void cfs(int edg_number, int sta, int end, int len) {
        edg[edg_number].e = end;
        edg[edg_number].dist = len;
        edg[edg_number].next = head[sta];
        head[sta] = edg_number;
        return ;
    }

    int edgend(int x) {
        return edg[x].e;
    }
    int edgdist(int x) {
        return edg[x].dist;
    }
    int edgnext(int x) {
        return edg[x].next;
    }

    int lastedg(int x) {
        return head[x];
    }
    void printGraphList() {
        for (int i = 1; i <= __nodeNum; i++) {
            cout << i << " :";
            for (int j = head[i]; j != -1; j = edg[j].next) {
                int e = edg[j].e, d = edg[j].dist;
                cout << "(" << e << " " << d << ") ";
            }
            cout << endl;
        }
        return ;
    }
    ~Graph() {
        head.clear();
        edg.clear();
    }
private:
    int __nodeNum, edgNum;
    vector<int> head;
    vector<edge> edg;  
};


class MinPath{
public:
    MinPath(Graph g, int sta):g(g), sta(sta){
        minpaths = vector<int>(g.nodeNum() + 1, INT_MAX);
        mark = vector<int>(g.nodeNum() + 1, 0);
    }
    void bellman_ford() {
        que.push(sta);
        minpaths[sta] = 0;
        while(!que.empty()) {
            int temp = que.front();
            que.pop(); 
            mark[temp] = 0;
            for (int i = g.lastedg(temp); i != -1; i = g.edgnext(i)) {
                int e = g.edgend(i), d = g.edgdist(i);
                if (minpaths[e] > minpaths[temp] + d) {
                    minpaths[e] = minpaths[temp] + d;
                    if (mark[e] == 0) {
                        que.push(e);
                        mark[e] = 1;
                    }
                }   
            }      
        }
        return ;
    }

    void printMinPath() {
        for (int i = 1; i <= g.nodeNum(); i++) {
            if (i != 1) cout << " ";        
            if (minpaths[i] == 0x3F3F3F3F) cout << -1;                    
            else cout << minpaths[i];
        }
        cout << endl;
        return ;
    }
    int minpath(int t) {
        return minpaths[t];
    }
private:
    int sta;
    queue<int> que;
    Graph g;
    vector<int> minpaths;
    vector<int> mark;
};

int main() {
    int n, m, s, t;
    cin >> n >> m >> s;
    Graph g(n, m);
    for (int i = 0; i < m; i++) {
        int a, b, c;
        cin >> a >> b >> c;
        g.cfs(i, a, b, c);
    }
    MinPath p(g, s);
    p.bellman_ford();
    p.printMinPath();
    /*while(cin >> t) {
        cout << p.minpath(t) << endl;
    }
    */
    return 0;
}

路径之和

路径之和最小-最小生成树

kruskal

#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdio>
#include<queue>
#include<vector>
using namespace std;

struct edge {
    int s, e, v;
};

bool cmp(const edge &a, const edge &b) {
    return a.v < b.v;
}

class Union {
public:
    Union() = default;
    Union(int n, int m) : n(n), m(m){
        my_union = vector<int>(n);
    }
    void init() {
        for (int i = 1; i <= this->n; i++) {
            my_union[i] = i;
        }
        return ;
    }

    int get(int x) {
        return my_union[x] = (x - my_union[x] ? get(my_union[x]) : x);
    }

    void merge(int a, int b) {
        my_union[a] = b;
    }
private:
    int n, m;
    vector<int> my_union;
};

int main() {
    int n, m;
    int already = 1, ans = 0;
    cin >> n >> m;
    vector<edge> edg(m);
    for (int i = 0; i < m; i++) {
        cin >> edg[i].s >> edg[i].e >> edg[i].v;
    }
    sort(edg.begin(), edg.end(), cmp);
    Union u(n, m);
    u.init();
    for (int i = 0; i <= m; i++) {
        int sr = u.get(edg[i].s), er = u.get(edg[i].e);
        if (sr != er) {
            already++;
            ans += edg[i].v;
            u.merge(sr, er);
            if (already == n) break;
        }
    }

    if (already == n) {
        cout << ans << endl;
    } else {
        cout << "orz" << endl;
    }  
    return 0;
}

prim

#include<iostream>
#include<queue>
#include<vector>
#include <climits>
using namespace std;
 
struct edge{
    int e, dist, next;
};

class Graph{
public:
    Graph() = default;
    Graph(int nodenum, int edgNum): __nodeNum(nodenum), edgNum(edgNum){
        head = vector<int>(nodenum, -1);
        edg = vector<edge>(edgNum); 
    }

    int nodeNum() {
        return __nodeNum;
    }
    void cfs(int edg_number, int sta, int end, int len) {
        edg[edg_number].e = end;
        edg[edg_number].dist = len;
        edg[edg_number].next = head[sta];
        head[sta] = edg_number;
        return ;
    }

    int edgend(int x) {
        return edg[x].e;
    }
    int edgdist(int x) {
        return edg[x].dist;
    }
    int edgnext(int x) {
        return edg[x].next;
    }

    int lastedg(int x) {
        return head[x];
    }
    ~Graph() {
        head.clear();
        edg.clear();
    }
private:
    int __nodeNum, edgNum;
    vector<int> head;
    vector<edge> edg;  
};


struct node{
    int now, dist;//dist:到达权值为多少的边到达这个点,越小越好
    bool operator< (const node &b)  const{
       return this->dist > b.dist;
    }
};

class MinTree{
public:
    MinTree(Graph g, int sta, int ans = 0, int already = 0):g(g), sta(sta), ans(ans), already(already){
        n = g.nodeNum();
        mark = vector<int>(n + 1, 0);
        dis = vector<int>(n + 1, INT_MAX);
    }
    void mintree() {
        que.push((node){sta, 0});
        while(!que.empty()) {
            node temp = que.top();
            que.pop(); 
            if (mark[temp.now] == 1) continue;
            mark[temp.now] = 1;
            ans += temp.dist;
            ++already;
            if (already == n) break;
            for (int i = g.lastedg(temp.now); i != -1; i = g.edgnext(i)) {
                int e = g.edgend(i), d = g.edgdist(i);
                if (mark[e] == 0 && dis[e] > d) {
                    dis[e] = d;
                    que.push((node){e, d});                
                }
                    
            }      
        }
        return ;
    }

    void print() {
        if (already == n) {
            cout << ans << endl;
        } else {
            cout << "arz" << endl;
        }
        return ;
    }

private:
    int sta, ans, already, n;
    priority_queue<node> que;
    Graph g;
    vector<int> mark, dis;
};

int main() {
    int n, m, s, t;
    cin >> n >> m >> s;
    Graph g(n, m);
    for (int i = 0; i < m; i++) {
        int a, b, c;
        cin >> a >> b >> c;
        g.cfs(i, a, b, c);
    }
    MinTree p(g, s);
    p.mintree();
    p.print();
    return 0;
}

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值