• UVA


    题意:给出一个无向图,然后你要输升序输出该图中 所有的桥。

    思路:使用tarjan对桥的求法性质:

    当且仅当无向边(u,v)为树枝的时候,需要满足dfn(u)<low(v),也就是v向上翻不到u及其以上的点,那么u-v之间一定能够有1条或者多条边不能删去,因为他们之间有一部分无环,是桥。            

    如果v能上翻到u那么u-v就是一个环,删除其中一条路径后,能然是连通的。所以最总就是使用low(v)>dfn(u)来判断是否为桥

    完整代码:

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <cmath>
    #include <algorithm>
    #include <vector>
    #include <stack>
    using namespace std;
    typedef long long LL;
    const double eps = 1e-8;
    const int inf = 0x3f3f3f3f;const int maxn = 1e3+10;
    const int max_edge = 1e6+5;
    struct Edge
    {
        int to, next;
        bool cut;
    }edge[max_edge];
    int tot, head[maxn];
    int id, dfn[maxn], low[maxn];
    int num;
    void addedge(int u, int v)
    {
        edge[tot].to = v;
        edge[tot].next = head[u];
        edge[tot].cut = false;
        head[u] = tot++;
    }
    //tarjan的割边求法 
    void tarjan(int u, int f)
    {
        //时间戳更新 
        dfn[u] = low[u] = ++id;
        for(int i = head[u]; i!=-1; i = edge[i].next)
        {
            int v = edge[i].to;
            if(v == f) continue;
            //深搜已经更新low值 
            if(!dfn[v])
            {
                tarjan(v, u);
                low[u] = min(low[u], low[v]);
                //tarjan算法割边确定的结论low[v]>dfn[u](桥>,割点>=) 
                if(low[v]>dfn[u])
                {
             //由于无向图边是连着存的,所以就用 ^ 得到所用有向边代替的另一个边 (0^1=1, 1^1=0),网上看到大佬的写法
             //当然我们也可以使用 奇数向下取偶,偶数向上取奇 
    edge[i].cut
    = edge[i^1].cut = true; num++; } } else low[u] = min(low[u], dfn[v]); } } void init() { id = num = tot = 0; memset(head, -1, sizeof(head)); memset(dfn, 0, sizeof(dfn)); memset(low, 0, sizeof(low)); } int main() { int n; while(~scanf("%d", &n)) { init(); int u, m, v; for(int i = 1; i<=n; i++) { scanf("%d (%d)", &u, &m); for(int j = 1; j<=m; j++) { scanf("%d", &v); addedge(u, v); addedge(v, u); } } for(int i = 0; i<n; i++) if(!dfn[i]) tarjan(i, i); vector<pair<int, int> >a; for(int u = 0; u<n; u++) for(int i = head[u]; i!=-1; i = edge[i].next) { //按升序排列 if(edge[i].cut && u < edge[i].to) a.push_back(make_pair(u, edge[i].to)); } sort(a.begin(), a.end()); printf("%d critical links ", num); for(int i = 0; i<a.size(); i++) printf("%d - %d ", a[i].first, a[i].second); printf(" "); } }
  • 相关阅读:
    重置mysql数据库密码
    windows下IIS+PHP解决大文件上传500错问题
    ecmobile中IOS版本中界面文字不显示的解决
    linux下重置mysql的root密码
    nginx下rewrite参数超过9个的解决方法
    android模拟器停在Waiting for HOME解决方案
    android模拟器没法通过localhost访问本地服务器的解决
    zend studio导入svn项目后不能代码提示的解决
    排序(1)

  • 原文地址:https://www.cnblogs.com/Tianwell/p/11317010.html
Copyright © 2020-2023  润新知