poj 1515 Street Directions(双连通分量)

来源:互联网 发布:python reduce 函数 编辑:程序博客网 时间:2024/05/14 20:02

题意:给出一个连通图,边是双向边,要求令尽可能多的双向边改成单向边,并且图还是连通的(强连通)。

思路:这题其实不太难搞。我们可以想一下,那些边是一定不能改造的?没错,是桥,如果桥被改成单向边,那么就不可能强连通,另外,对于一个双连通分量来说,一定可以把它们的边改成单向并且还是连通的。这样,算法就比较明确了,对于桥来说,不能改造,对于一个双连通分量来说,改造它的所有边。如何改造双连通分量中的边?其实仔细想一下就可以发现,tarjan的过程中的遍历顺序恰好是一个可行的方案,因此,可以再tarjan的过程中直接把结果输出,用一个数组标记一条边是否被改造即可。


代码:


#include<iostream>#include<cstdio>#include<cstring>#include<string>#include<algorithm>#include<map>#include<queue>#include<set>#include<stack>#include<cmath>#include<vector>#define inf 0x3f3f3f3f#define Inf 0x3FFFFFFFFFFFFFFFLL#define eps 1e-9#define pi acos(-1.0)using namespace std;typedef long long ll;const int maxn=1000+10;const int maxm=10000+10;struct Edge{    int v,next;    Edge(){};    Edge(int vv,int nx){v=vv;next=nx;}}edges[maxm<<1];int head[maxn],nEdge;int pre[maxn],id[maxn],ebc_cnt,dfs_clock;bool flag[maxm<<1];stack<int>S;void AddEdge(int u,int v){    edges[++nEdge]=Edge(v,head[u]);    head[u]=nEdge;    edges[++nEdge]=Edge(u,head[v]);    head[v]=nEdge;}int tarjan(int u,int fa){    int lowu=pre[u]=++dfs_clock;    S.push(u);    for(int k=head[u];k!=-1;k=edges[k].next)    {        int v=edges[k].v;        if(!pre[v])        {            int lowv=tarjan(v,u);            lowu=min(lowu,lowv);            if(lowv>pre[u])            {                printf("%d %d\n",u,v);                printf("%d %d\n",v,u);                flag[k]=flag[k^1]=true;                ebc_cnt++;                while(true)                {                    int x=S.top();S.pop();                    id[x]=ebc_cnt;                    if(x==v) break;                }            }        }        else if(pre[v]<lowu&&v!=fa)            lowu=min(lowu,pre[v]);        if(!flag[k]&&v!=fa)        {            flag[k]=flag[k^1]=true;            printf("%d %d\n",u,v);        }    }    return lowu;}void find_ebc(int n){    memset(pre,0,sizeof(pre));    memset(flag,0,sizeof(flag));    memset(id,0,sizeof(id));    while(!S.empty()) S.pop();    dfs_clock=ebc_cnt=0;    for(int i=1;i<=n;++i)        if(!pre[i]) tarjan(i,-1);}int main(){    //freopen("in.txt","r",stdin);    //freopen("out.txt","w",stdout);    int n,m;    int tcase=0;    while(~scanf("%d%d",&n,&m))    {        if(n==0&&m==0) break;        printf("%d\n\n",++tcase);        int u,v;        memset(head,0xff,sizeof(head));        nEdge=-1;        for(int i=0;i<m;++i)        {            scanf("%d%d",&u,&v);            AddEdge(u,v);        }        find_ebc(n);        printf("#\n");    }    return 0;}

0 0
原创粉丝点击