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\n",u,v);

            if(isbge[id])

                printf("%d %d\n",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\n\n",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

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

你可能感兴趣的:(tree)