首页 > 代码库 > POJ 1515 Street Directions --一道连通题的双连通和强连通两种解法

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 1006vector<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

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