zoukankan      html  css  js  c++  java
  • 图论模板集合

    1.拓扑排序

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <string>
    #include <algorithm>
    #include <set>
    #include <vector>
    using namespace std;
    #define maxn 105
    typedef long long ll;
    vector<int> G[maxn];
    struct node{
        int time;
        int id;
        bool operator < (const node & rhs)const{
            return time > rhs.time;
        }
    }nodes[maxn];
    int n;
    bool vis[maxn];
    int nowTime = 0;
    void dfs(int u){
        nowTime ++;
        vis[u] = true;
        for(int i = 0;i < G[u].size();i ++){
            int v = G[u][i];
            if(!vis[v]) dfs(v);
        }
        nowTime ++;s
        nodes[u].time = nowTime;
    }
    void top(void){
        for(int i = 1;i <= n;i ++){
            if(!vis[i]){
                dfs(i);
            }
        }
    }
    
    int main(void){
        
        cin >> n;
        memset(vis,false,sizeof(vis));
        for(int i = 1;i <= n;i ++){
            int b;
            nodes[i].id = i;
            while(cin >> b && b != 0){
                G[i].push_back(b);
            }
        }
        nowTime = 0;
        top();
        sort(nodes+1,nodes+n+1);
        for(int i = 1;i <= n;i ++){
            cout <<  nodes[i].id << " ";               //按拓扑排序输出节点 
        }
        cout << endl;
        return 0;
    } 
    View Code

    2.无向图割点

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <cstring>
    #include <vector>
    #define maxn 100005
    using namespace std;
    vector<int> G[maxn];
    int dfn[maxn],vis[maxn],low[maxn];     
    bool isGedian[maxn];                  //标记该点是否是割点 
    int fa[maxn];                         //父亲节点 
    int depth;                         
    int root;
    int ans;
    void init(){
        memset(isGedian,0,sizeof(isGedian));
        memset(fa,0,sizeof(fa));
        memset(vis,0,sizeof(vis));
        for(int i = 0;i < maxn;i ++){
            G[i].clear();
        }
    }
    void dfs(int cur,int depth){
         int cnt = 0;                       //记录当前节点的孩子个数 
         low[cur] = dfn[cur] = depth;
         vis[cur] = true;
         for(int i = 0;i < G[cur].size();i ++){
             int v = G[cur][i];
            if(!vis[v] && v != fa[cur]){
                fa[v] = cur;
                dfs(v,depth+1);
                cnt ++;
                low[cur] = min(low[cur],low[v]);
                if(low[v] >= dfn[cur] && root!= cur){
                    if(!isGedian[cur]){
                        ans ++;
                    }
                    isGedian[cur] = true;
                }
            }
            else{
                low[cur] = min(low[cur],dfn[v]);
            }
         }
         if(root == cur && cnt > 1){
            if(!isGedian[cur]){
                ans ++;
            }
            isGedian[cur] = true;
         }
    }
    int main()
    {
        int n,a,b;
        while(cin >> n && n){
            ans = 0;
            init();
            while(cin >> a && a){
                while(getchar() != '
    ')
                {
                    cin >> b;
                    G[a].push_back(b);
                    G[b].push_back(a);
                }
            }
            root = 1;
            dfs(1,0);
            cout << ans << endl;
        }
        return 0;
    }
    View Code

     3.强连通分量

    #include <iostream>
    #include <algorithm>
    #include <cstring>
    #include <vector>
    #define maxn 10005
    using namespace std;
    vector<int> G[maxn],Gt[maxn]; //Gt存放补图
    vector<int> S;
    int vis[maxn];
    int sccno[maxn];              //每个节点所在强连通分量的序号
    int scc_cnt;                  //强连通分量个数
    int outdegree[maxn];          //连通分量的出度
    
    void dfs1(int u){             //目的,按每个节点结束搜索的时间排序
        if(vis[u]) return;
        vis[u] = 1;
        for(int i = 0;i < G[u].size();i ++){
            int v = G[u][i];
            dfs1(v);
        }
        S.push_back(u);
    }
    void dfs2(int u){
        if(sccno[u])    return;
        sccno[u] = scc_cnt;
        for(int i = 0;i < Gt[u].size();i ++){
            int v = Gt[u][i];
            dfs2(v);
        }
    }
    void find_scc(int n){
        S.clear();
        scc_cnt = 0;
        memset(sccno,0,sizeof(sccno));
        memset(vis,0,sizeof(vis));
        memset(outdegree,0,sizeof(outdegree));
        for(int i = 1;i <= n;i ++){
            dfs1(i);
        }
        for(int i = n-1;i >= 0 ;i --){
            if(!sccno[S[i]]){
                scc_cnt ++;
                dfs2(S[i]);
            }
        }
    }
    View Code

     4.单源最短路径Dijkstra

    #include <iostream>
    #include <algorithm>
    #include <cstring>
    #include <cstdio>
    #include <vector>
    #include <queue>
    #define maxn 105
    #define INF 1e9+9 
    using namespace std;
    int d[maxn];                //s到各个边的距离 
    int head[maxn];
    bool done[maxn];         //是否已完全标号 
    int edgesCnt;              //边的数量 
    int n;
    struct Edge{
        int to;              //边的终点 
        int dist;            //边的长度 
        int next;            //下一条边的编号 
    }edges[maxn*maxn];
    struct HeapNode{
        int u;                 //节点编号 
        int d;                   //节点到源节点的距离 
        bool operator < (const HeapNode& rhs) const{
            return d > rhs.d;
        }
    };
    void init(){
        edgesCnt = 0;
        memset(head,-1,sizeof(head));
    }
    void addEdge(int from,int to,int dist){
        edges[edgesCnt] = {to,dist,head[from]};
        head[from] = edgesCnt; 
        edgesCnt ++;
    }
    void Dijkstra(int s){
        priority_queue<HeapNode> Q;
        for(int i = 0;i <= n;i ++) d[i] = INF;
        memset(done,false,sizeof(done));
        d[s] = 0;
        Q.push((HeapNode){s,0});
        while(!Q.empty()){
            HeapNode x = Q.top();
            Q.pop();
            int u = x.u;
            if(done[u]) continue;
            done[u] = true;
            for(int i = head[u];i != -1;i = edges[i].next){
                Edge e = edges[i];
                int v = e.to;
                if(d[v] > d[u] + e.dist){
                    d[v] = d[u] + e.dist;
                    Q.push((HeapNode){v,d[v]});
                }
            }
        }
    }
    View Code
  • 相关阅读:
    综合疑问
    MySQL查询优化器工作原理解析
    mysql配置文件参数详解
    MySQL查看、创建和删除索引的方法
    删除maven仓库中的lastUpdate文件
    加密算法的概述
    .bat脚本基本命令语法
    spring-core中@Order和Ordered接口的源码解析说明
    spring-context中@Profile注解的源码解析说明
    spring-context中@Bean的源码解析说明和它与其他注解的结合使用
  • 原文地址:https://www.cnblogs.com/zhangjialu2015/p/5721425.html
Copyright © 2011-2022 走看看