图论练习题

图论练习题主要包括:
1. dfs
2. bfs
3. kruskal
4. prim
5. dijsktra

/*************************************************************************
    > File Name: graph.cpp
    > Author: Yuji CAO
    > Mail: [email protected]
    > Created Time: 2016年08月13日 星期六 20时53分41秒
 ************************************************************************/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include

using namespace std;
class UnionFind {
public:
    UnionFind(int n) {
        s.resize(n);
        for (int i = 0; i < n; ++i) {
            s[i] = i;
        }
    }
    void uni(int t1, int t2) {
        int r1 = find(t1);
        int r2 = find(t2);
        if (r1 != r2) {
            s[r2] = r1;
        }
    }
    int find(int t) {
        if (s[t] == t) return t;
        s[t] = find(s[t]);
        return s[t];
    }
    void print() {
        for (int i = 0; i < s.size(); ++i) {
            cout<"\t";
        }
        cout<for (int i = 0; i < s.size(); ++i) {
            cout<"\t";
        }
        cout<private:
    vector<int> s;
};

namespace graph {
    struct G {
        vector<int> getAdj(int cur) {
            if (nodes.find(cur) != nodes.end())
                return nodes[cur];
            else {
                vector<int> a; 
                return a;
            }
        }
        void setAdj(int from, vector<int>& adjs) {
            nodes[from] = adjs;
        }
        int size() {
            return (int)nodes.size();
        }
    private:
        unordered_map<int,vector<int> > nodes;
    };
    struct GWeight {
        GWeight(int n) {
            matrix.resize(n);
            for (int i = 0; i < n; ++i) {
                matrix[i].resize(n);
            }
            for (int i = 0; i < n; ++i) {
                for (int j = 0; j < n; ++j) {
                    if (i == j) matrix[i][j] = 0;
                    else matrix[i][j] = numeric_limits<int>::max();
                }
            }
        }
        int getWeight(int i, int j) {
            return matrix[i][j];
        }
        int setWeight(int i, int j, int w) {
            matrix[i][j] = w;
        }
        int size() {
            return (int) matrix.size();
        }
    private:
        vector<vector<int> > matrix;
    };
    static GWeight fromFile2(string file) {
        ifstream stream;
        stream.open(file, ios::in);
        char buffer[1024];
        int n;
        stream>>n;
        GWeight g(n);
        int i = 0;
        int j = 0;
        stream.getline(buffer, 1024);
        while(stream.getline(buffer, 1024)) {
            string buf(buffer);
            int pre = -1;
            for (int k = 0; k < buf.size(); ++k) {
                if (buf[k] == ',') {
                    /*
                    0 1 2 3 4 5 6
                    a b , c d e ,
                    */
                    int len = k - 1 - pre;
                    string word = buf.substr(pre + 1, len);
                    int w = atoi(word.c_str());
                    pre = k;
                    if (word == "#") {
                        w = numeric_limits<int>::max();
                    }
                    g.setWeight(i, j++ % n, w);
                }
            }
            i++;
        }
        stream.close();
        return g;
    }
    static G fromFile(string file) {
        G g;
        ifstream stream;
        stream.open(file, ios::in);
        char buffer[1024];
        while(stream.getline(buffer,1024)) {
            string buf(buffer);
            int pre = -1;
            int index = -1;
            vector<int> adjs;
            for (int i = 0; i < buf.size(); ++i) {
                if (buf[i] == ',') {
                    int len = i - 1 - pre;
                    string word = buf.substr(pre + 1, len);
                    int wordInt = atoi(word.c_str());
                    if (index == -1) {
                        index = wordInt;
                    } else {
                        adjs.push_back(wordInt);
                    }
                    pre = i;
                }
            }
            g.setAdj(index, adjs);
        }
        stream.close();
        return g;
    };
    /*  
     *  0
     *  |
     *  1---2---3---
     *  |   |       \
     *  4---5---6----7  
     *  1->2,4
     *  2->1,3,5
     *  3->2,7
     *  4->1,5
     *  5->2,4,6
     *  6->5,7
     *  7->3,6
     *
     *  0->0 0
     *  0->1 1
     *  0->2 2
     *  0->3 3
     *  0->4 2
     *  0->5 3
     *  0->6 4
     *  0->7 4
     * bfs
     *  0,1,2,4,3,5,7,6
     * dfs
     *  0,1,2,3,7,6,5,4
     */
    namespace mst {
        struct Edge {
            int from;
            int to;
            int w;
            Edge():from(-1),to(-1),w(numeric_limits<int>::max()){}
            Edge(int from, int to, int w) : from(from), to(to), w(w){}
            bool operator < (const Edge& r) const {
                return this->w > r.w;
            }
            Edge& operator=(const Edge& r) {
                from = r.from;
                to = r.to;
                w = r.w;
                return *this;
            }
            string toString() {
                stringstream ss;
                ss<<"[from:"<",to:"<",w:"<"]";
                return ss.str();
            }
        };
    };
    namespace ssp {
        struct Dist {
            int to;
            int dist;
            Dist(int to, int dist):to(to), dist(dist){}
            bool operator < (const Dist& r) const {
                return dist > r.dist;
            }
        };
    };
    class Graph {
    public:
        vector<int> bfs(G& g, int s, vector<int>& dist) {
            dist.resize(g.size());
            for (int i = 0; i < g.size(); ++i) {
                dist[i] = 0;
            }
            vector<int> ans;
            queue<int> q;
            q.push(s);
            ans.push_back(s);
            unordered_set<int> visited;
            visited.insert(s);
            while(!q.empty()) {
                int f = q.front();
                q.pop();
                vector<int> adjs = g.getAdj(f);
                for (auto adj : adjs) {
                    if (visited.find(adj) == visited.end()) {
                        ans.push_back(adj);
                        visited.insert(adj);
                        q.push(adj);
                        dist[adj] = 1 + dist[f];
                    }
                }
            }
            return ans;
        }
        vector<vector<int> > dfs(G& g) {
            vector<vector<int> > ans;
            unordered_set<int> visited;
            for (int i = 0; i < g.size(); ++i) {
                vector<int> ansEle;
                if (visited.find(i) == visited.end()) {
                    dfsInner(g, i, ansEle, visited);
                    ans.push_back(ansEle);
                }
            }
            return ans;
        }
        vector spanningTree(GWeight& g, bool k = false) {
            if (k)return kruskal(g);
            return prim(g);
        }
        vector<int> shortestPath(GWeight& g, int s) {
            return dijkstra(g, s);
        }
        void shortestPathOfAll(const G& g) {

        }
    private:
        void dfsInner(G& g, int s, vector<int>& ans, unordered_set<int>& visited) {
            visited.insert(s);
            ans.push_back(s);
            vector<int> adjs = g.getAdj(s);
            for (auto adj : adjs) {
                if (visited.find(adj) == visited.end()) { 
                    dfsInner(g, adj, ans, visited);
                } 
            }
        }
        vector kruskal(GWeight& g) {
            UnionFind uf(g.size());
            priority_queue q;
            for (int i = 0; i < g.size(); ++i) {
                for (int j = 0; j < g.size(); ++j) {
                    if (g.getWeight(i, j) != numeric_limits<int>::max()) {
                        mst::Edge e (i, j , g.getWeight(i, j));
                        q.push(e);
                    }
                }
            }
            vector ans;
            while (!q.empty()) {
                mst::Edge e = q.top(); 
                if (uf.find(e.from) != uf.find(e.to)) {
                    ans.push_back(e); 
                    uf.uni(e.from, e.to);
                }
                q.pop();
            }
            return ans;
        }
        //prim
        int extractMin(vector& d, unordered_set<int>& visited, int n) {
            int ans = -1;
            int min = numeric_limits<int>::max();
            for (int i = 0; i < n; ++i) {
                if(visited.find(i) != visited.end()) continue;
                if (min > d[i].w) {
                    min = d[i].w;
                    ans = i;
                }
            }
            return ans;
        }
        vector prim(GWeight& g) {
            unordered_set<int> visited;
            vector dd;
            dd.resize(g.size());
            mst::Edge edge(0,0,0);
            dd[0] = edge;
            vector ans;
            for (int i = 0; i < g.size(); ++i) {
                int v = extractMin(dd, visited, g.size());
                if (!(dd[v].to == v && v == 0)) {
                    ans.push_back(dd[v]);
                }
                visited.insert(v);
                for (int u = 0; u < g.size(); ++u) {
                    if (g.getWeight(v, u) < dd[u].w) {
                        int d = g.getWeight(v,u);
                        mst::Edge e(v, u, d);
                        dd[u] = e;
                    }
                }
            }
            return ans;
        }
        //dijkstra
        void init(GWeight& g, int s, priority_queue& q, vector<int>& dist) {
            dist.resize(g.size());
            for (int i = 0; i < g.size(); ++i) {
                int m = numeric_limits<int>::max();
                if (i == s) {
                    ssp::Dist d(i, 0);
                    d.dist = 0;
                    q.push(d);
                    m = 0;
                }
                dist[i] = m;
            }
        }
        vector<int> dijkstra(GWeight& g, int s) {
            vector<int> dist;
            priority_queue queue;
            init(g, s, queue, dist);
            unordered_set<int> visited;
            visited.insert(0);

            for (int i = 0; i < g.size(); ++i) {
                ssp::Dist top = queue.top();
                queue.pop();
                int f = top.to;
                visited.insert(top.to);
                for (int j = 0; j < g.size(); ++j) {
                    int v = g.getWeight(f, j);
                    if (visited.find(j) != visited.end()) continue;
                    if (v == numeric_limits<int>::max()) continue;
                    if (dist[j] > v + dist[f]) {
                        dist[j] = v + dist[f];
                        ssp::Dist d(j, dist[j]);
                        queue.push(d);
                    }
                }
            }
            return dist;
        }
    };
    /*
    class DirectGraph {
    public:
        vector topologicalSort(G& g) {
            vector ans;
            for (int i = 0; i < g.size(); ++i) {
                if ()
            }
            return ans;
        }
        void shortestPath(G& g) {
            return;
        }
        vector > strongConnectedComponent(G& g) {
            vector > ans;
            return ans;
        }
    };
    class DAG {
    public:
        void shortestPath(const G& g, int s) {

        }
        void longestPath(const G& g, int s) {

        }
    };
    */
};
int main() {
    graph::G g = graph::fromFile("./g.txt");
    graph::Graph gOpt;

    cout<<"breadth first search"<vector<int> dist;
    vector<int> ans = gOpt.bfs(g, 0, dist);
    for (int i = 0; i < dist.size(); ++i) {
        cout<<"0->"<":\t"<for (int ele : ans) {
        cout<",";
    }
    cout<cout<<"depth first search"<auto ans1 = gOpt.dfs(g);
    for (auto eleI : ans1) {
        for (auto eleJ : eleI) {
            cout<",";
        }
        cout<"./gw.txt");

    cout<<"spanning tree kruskal"<auto ans2 = gOpt.spanningTree(gw, true);
    for (auto ele : ans2) {
            cout<cout<<"spanning tree prim"<auto ans3 = gOpt.spanningTree(gw, false);
    for (auto ele : ans3) {
            cout<cout<<"shortest path dijkstra"<auto ans4 = gOpt.shortestPath(gw, 0);
    int i = 0;
    for (auto ele : ans4) {
            cout<<0<<"->"<":\t"<1;
    }
    return 0;
}

你可能感兴趣的:(算法)