zoukankan      html  css  js  c++  java
  • c_pat_哈密顿回路 & 最大点集 & 是否是旅行商路径 & 欧拉路径 & 最深的根(邻接矩阵存图)

    Hamiltonian Cycle

    哈密顿回路问题是找到一个包含图中每个顶点的简单回路。你需要做的是判断给定路径是否为哈密顿回路。

    充分条件
    从任意起点出发,都具有以下性质的回路成为哈密顿回路:

    • 起点=终点
    • 每个待判序列给出的结点个数等于n+1,否则,必然经过某一个结点多次
    • 1~n个结点都能被访问

    坑:写则顶点编号从1N,暗地里却设为12N...

    #include<bits/stdc++.h>
    using namespace std;
    const int N=205;
    int n,m,Q,a[2*N],g[N][N];
    
    bool chk(int sz) {
        if (sz!=n+1 || a[0]!=a[sz-1]) return false;
        bool vis[N]; memset(vis, false, sizeof vis);
        for (int i=1; i<sz; i++) {
            if (!g[a[i-1]][a[i]]) return false;
            vis[a[i]]=1;
        } 
        for (int i=1; i<=n; i++) if (!vis[i])
            return false;
        return true;
    }
    int main() {
        std::ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
        cin>>n>>m;
        for (int i=0; i<m; i++) {
            int u,v; cin>>u>>v;
            g[u][v]=g[v][u]=1;
        }
        cin>>Q;
        while (Q--) {
            int sz; cin>>sz;
            for (int i=0; i<sz; i++) cin>>a[i];
            cout << (chk(sz) ? "YES" : "NO")<<'
    ';
        } 
        return 0;
    }
    

    Maximal Clique

    在一个无向图中,如果一个顶点子集满足子集内的任意两个不同顶点之间都是相连的,那么这个顶点子集就被称为一个团。
    如果一个团不能通过加入某个新的顶点来扩展成一个更大的团,那么该团就被称为最大团。
    现在,你需要判断给定顶点子集能否构成一个最大团。

    思路

    #include<bits/stdc++.h>
    using namespace std;
    const int N=205;
    int n,m,a[N],g[N][N];
    bool is_clique(int sz) {
        for (int i=0; i<sz-1; i++)
        for (int j=i+1; j<sz; j++) if (!g[a[i]][a[j]])
            return false;
        return true;
    } 
    bool is_maximal(int sz) {
        bool in_a[N]; memset(in_a, false, sizeof in_a);
        for (int i=0; i<sz; i++) in_a[a[i]]=true;
    
        for (int i=1; i<=n; i++) if (!in_a[i]) { //如果不在a中的点能和a中所有点相连,则不是最大点集;换句话说,只要有一个不在a中的顶点不和a中所有点相连,则认定这个点集是最大的
            bool is_allconn=true;
            for (int j=0; j<sz; j++) if (!g[i][a[j]]) {
                is_allconn=false;
                break;
            }
            if (is_allconn) return false;
        }
        return true;
    }
    int main() {
        std::ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
        cin>>n>>m;
        for (int i=0; i<m; i++) {
            int u,v; cin>>u>>v;
            g[u][v]=g[v][u]=true;
        }
        int q; cin>>q;
        while (q--) {
            int k; cin>>k;
            for (int i=0; i<k; i++) cin>>a[i];
            if (is_clique(k)) {
                cout<<(is_maximal(k) ? "Yes":"Not Maximal")<<'
    ';
            } else {
                cout<<"Not a Clique
    ";
            }
        }
        return 0;
    }
    

    Travelling Salesman Problem

    请你从给定的路径列表中找到最接近旅行商问题的解的路径。
    输出 Shortest Dist(X) = TotalDist,X 是最接近旅行商问题解决方案的回路编号,TotalDist 是其总距离。

    思路
    tsp问题就是求解哈密顿回路

    #include<bits/stdc++.h>
    using namespace std;
    const int N=205, inf=0x3f3f3f3f;
    int n,m,a[N],g[N][N];
    int get_cost(vector<int>& v) {
        int n=v.size(), cost=0;
        for (int i=1; i<v.size(); i++) cost+=g[v[i-1]][v[i]]; 
        return cost;
    }
    bool is_all_conn(vector<int>& v) {
        for (int i=1; i<v.size(); i++) if (g[v[i-1]][v[i]]<0)
            return false;
        return true;
    }
    int main() {
        std::ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
        cin>>n>>m; memset(g, -inf, sizeof g);
        for (int i=0; i<m; i++) {
            int u,v,w; cin>>u>>v>>w;
            g[u][v]=g[v][u]=w;
        }
        int q, minCost=inf, minCostIdx=0; cin>>q;
        for (int c=1; c<=q; c++) {
            int k; cin>>k;
            vector<int> v(k);
            unordered_set<int> st;
            for (int i=0; i<k; i++) cin>>v[i], st.insert(v[i]);
            int conn=is_all_conn(v);
            if (st.size()<n || v.front()!=v.back() || !conn) {
                int cost=get_cost(v);
                if (!conn) printf("Path %d: NA (Not a TS cycle)
    ", c);
                else printf("Path %d: %d (Not a TS cycle)
    ", c, cost);
            } else {
                int cost=get_cost(v);
                if (v.size()==n+1) {
                    printf("Path %d: %d (TS simple cycle)
    ", c, cost);
                } else printf("Path %d: %d (TS cycle)
    ", c, cost);
                if (cost<minCost) minCost=cost, minCostIdx=c;
            }
        }
        printf("Shortest Dist(%d) = %d", minCostIdx, minCost);
        return 0;
    }
    

    Eulerian Path

    事实证明,如果一个连通图的所有顶点的度数都为偶数,那么这个连通图具有欧拉回路,且这个图被称为欧拉图。
    如果一个连通图中有两个顶点的度数为奇数,其他顶点的度数为偶数,那么所有欧拉路径都从其中一个度数为奇数的顶点开始,并在另一个度数为奇数的顶点结束。具有欧拉路径但不具有欧拉回路的图被称为半欧拉图。
    现在,给定一个无向图,请你判断它是欧拉图、半欧拉图还是非欧拉图。

    模拟即可

    #include<bits/stdc++.h>
    using namespace std;
    const int N=505;
    vector<int> g[N];
    int d[N], vis[N];
    int dfs(int u) {
        int c=1;
        vis[u]=1;
        for (int v : g[u]) if (!vis[v]) {
            c+=dfs(v);
        }
        return c;
    }
    int main() {
        std::ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
        int n,m; cin>>n>>m;
        for (int i=0; i<m; i++) {
            int u,v; cin>>u>>v;
            g[u].push_back(v);
            g[v].push_back(u);
            d[u]++, d[v]++;
        }
        int odd_degree=0;
        for (int i=1; i<=n; i++) if ((d[i]&1)==1) 
            odd_degree++;
        int c=dfs(1);
        for (int i=1; i<=n; i++) {
            cout<<d[i];
            if (i!=n) cout<<' ';
        }
        cout<<'
    ';
        if (c==n) {
            if (odd_degree==0) cout<<"Eulerian
    ";
            else if (odd_degree==2) cout<<"Semi-Eulerian
    ";
            else cout<<"Non-Eulerian
    ";
        } else {
            cout<<"Non-Eulerian
    ";
        }
        return 0;
    }
    

    Deepest Root

    一个无环连通图可以被视作一个树。树的高度取决于所选取的根节点。现在,你要找到可以使得树的高度最大的根节点。
    思路
    并查集检查树的合法性+暴力算最大深度maxd,并找到深度为maxd的结点

    #include<bits/stdc++.h>
    using namespace std;
    const int N=1e4+5;
    int fa[N];
    vector<int> g[N];
    int find(int u) {
        return fa[u]==u ? u : fa[u]=find(fa[u]);
    }
    void merge(int u, int v) {
        int fu=find(u), fv=find(v);
        if (fu!=fv)  fa[fu]=fv;
    }
    int get_dep(int u, int fa) {
        int d=1;
        for (int v : g[u]) if (v!=fa) {
            d=max(d, get_dep(v,u)+1);
        }
        return d;
    }
    int main() {
        std::ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
        int n; cin>>n;
        for (int i=1; i<=n; i++) fa[i]=i;
        for (int i=1; i<n; i++) {
            int u,v; cin>>u>>v;
            g[u].push_back(v), g[v].push_back(u);
            merge(u,v);
        }
        int cnt=0;
        for (int i=1; i<=n; i++) if (fa[i]==i) {
            cnt++;
        }
        if (cnt>1) {
            printf("Error: %d components
    ",cnt);
        } else {
            vector<int> v;
            int maxd=0;
            //for (int i=1; i<=n; i++) maxd=max(maxd, get_dep(i,-1));
            //for (int i=1; i<=n; i++) if (get_dep(i,-1)==maxd) v.push_back(i);
            for (int i=1; i<=n; i++) { //为什么这样会高效一些
                int d=get_dep(i,-1);
                if (d>maxd) {
                    maxd=d;
                    v.clear();
                    v.push_back(i);
                } else if (d==maxd) {
                    v.push_back(i);
                }
            }
            sort(v.begin(), v.end());
            for (int droot : v) printf("%d
    ",droot);
        }
        return 0;
    }
    
  • 相关阅读:
    从零开始搭建EasyDarwin环境——Linux系统开发环境Golang的搭建
    TSINGSEE青犀视频直播关键帧和空白关键帧都起到什么作用?
    TSINGSEE青犀视频平台监控程序新增按时间检测的实现
    TSINGSEE青犀视频开发AI识别dlib使用GPU如何激活?
    EasyCVR/EasyGBS程序运行为什么会出现too many open files?
    一篇文章让你了解视频监控系统搭建过程中如何选择存储方式
    MS SQL Server树型结构数据显示的SQL语句(纯SQL语句,不用函数)
    oracle中解决汉字无法显示、输入问题
    福州某火锅城餐饮收费系统查询代码
    (原创)基于关系数据库系统链式存储的树型结构数据,求某结点下的子树所有结点算法(tsql语言实现)
  • 原文地址:https://www.cnblogs.com/wdt1/p/13745654.html
Copyright © 2011-2022 走看看