• POJ 1515 Street Directions --一道连通题的双连通和强连通两种解法


    题意:将一个无向图中的双向边改成单向边使图强连通,问最多能改多少条边,输出改造后的图。

    分析:

    1.双连通做法:

    双连通图转强连通图的算法:对双连通图进行dfs,在搜索的过程中就能按照搜索的方向给所有边定向,其中桥不能改造,只能保留双向边。

    代码:

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <cmath>
    #include <cstdlib>
    #include <algorithm>
    #include <vector>
    #include <queue>
    using namespace std;
    #define N 1006
    
    vector<pair<int,int> > G[N];
    int dfn[N],low[N];
    int Time,vis[N];
    bool isbge[2000010],used[2000010];
    int n,m,cnt;
    
    void Tarjan(int u,int father)
    {
        low[u] = dfn[u] = ++Time;
        vis[u] = 1;
        for(int i=0;i<G[u].size();i++)
        {
            int v = G[u][i].first;
            int id = G[u][i].second;
            if(v == father)
                continue;
            if(!vis[v])
            {
                Tarjan(v,u);
                low[u] = min(low[u],low[v]);
                if(dfn[u] < low[v])
                    isbge[id] = 1;
            }
            else
                low[u] = min(low[u],dfn[v]);
        }
    }
    
    void dfs(int u,int fa)
    {
        vis[u] = 1;
        for(int i=0;i<G[u].size();i++)
        {
            int v = G[u][i].first;
            int id = G[u][i].second;
            if(!used[id])
            {
                used[id] = 1;
                printf("%d %d
    ",u,v);
                if(isbge[id])
                    printf("%d %d
    ",v,u);
                if(!vis[v])
                    dfs(v,u);
            }
        }
    }
    
    int main()
    {
        int i,j,u,v;
        int cs = 1;
        while(scanf("%d%d",&n,&m)!=EOF && (n||m))
        {
            for(i=0;i<=n;i++)
            {
                G[i].clear();
                vis[i] = 0;
                low[i] = dfn[i] = 0;
            }
            memset(used,0,sizeof(used));
            memset(isbge,0,sizeof(isbge));
            Time = 0;
            cnt = 0;  //id
            for(i=0;i<m;i++)
            {
                scanf("%d%d",&u,&v);
                G[u].push_back(make_pair(v,cnt));
                G[v].push_back(make_pair(u,cnt++));  //属于一条边
            }
            for(i=1;i<=n;i++)
                if(!dfn[i])
                    Tarjan(i,-1);
            memset(vis,0,sizeof(vis));
            printf("%d
    
    ",cs++);
            for(i=1;i<=n;i++)
                if(!vis[i])
                    dfs(1,-1);
            puts("#");
        }
        return 0;
    }
    View Code

    2.强连通做法:

    参见:http://blog.csdn.net/new_c_yuer/article/details/6733623

    主要思想:在同一个连通分量里,保留单向边即可,否则需要保留双向边。

  • 相关阅读:
    快速排序及其优化
    JVM基础:深入学习JVM堆与JVM栈(转)
    java 反射简介(转载)
    java 泛型简介(转载)
    Java 注解简介
    JVM入门必看——JVM结构
    Java多线程详解(转载)
    SpringMVC 实现文件的上传与下载
    死锁简介
    SQL的模糊查询(转载)
  • 原文地址:https://www.cnblogs.com/whatbeg/p/3856242.html
Copyright © 2020-2023  润新知