UVA 796 Critical Links (tarjan算法求割边)

  这是在kuangbin的题目里看到的,不得不吐槽一下,题目中居然没给出数据范围,还是我自己猜的~本来是一道挺裸的题,但是我wa了好多次,原因就是这里面有两个坑点,1重边特判,2输出时左边必须比右边小。

但是我之前说过,在判断割边的时候只需要直接记录就可以了,因为每条边只会访问一次,但其实这是取决于建图方式的,题目中给出了每个点都与之相连的点,所以我们建出的边一定会有重复的,所以需要用map去重一下,可以在建图的时候就判断(因为没有多重边),也可以在收集割边的时候判断。代码如下:

#include<map>
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
map<int,int>ma;
#define maxn 10010
struct EDGE
{
    int to,nxt;
} edge[10*maxn];
int tot,n,dfn[maxn],low[maxn],head[maxn],all,resnum;
void add_edge(int u,int v)
{
    edge[tot].to = v;
    edge[tot].nxt = head[u];
    head[u] = tot++;
}
void init()
{
    memset(low,0,sizeof(low));
    memset(dfn,0,sizeof(dfn));
    all = 0;
    resnum = 0;
    ma.clear();
}
bool mul(int u,int v)
{
    if(ma[u*maxn+v] || ma[v*maxn+u]) return true;
    ma[u*maxn+v] = ma[v*maxn+u] = 1;
    return false;
}
struct Node
{
    int x,y;
};
Node out[maxn];
void tarjan(int u,int fa)
{
    dfn[u] = low[u] = ++all;
    for(int i = head[u]; i != -1; i = edge[i].nxt)
    {
        int v = edge[i].to;
        if(!dfn[v])
        {
            tarjan(v,u);
            low[u] = min(low[u],low[v]);
            if(low[v] > dfn[u])
            {
                if(!mul(u,v))
                {
                    int tmpu = u,tmpv = v;
                    if(tmpu > tmpv)
                        swap(tmpu,tmpv);
                    out[resnum].x = tmpu;
                    out[resnum].y = tmpv;
                    resnum++;
                }
            }
        }
        else if(v != fa) low[u] = min(low[u],dfn[v]);
    }
    return ;
}
bool cmp(Node a,Node b)
{
    if(a.x != b.x) return a.x < b.x;
}
int getnum(char *a)
{
    int lena = strlen(a);
    int num = 0,jw = 1;
    for(int i = 1; i < lena; i++)
    {
        if(a[i] == ')')
        {
            for(int j = i-1; j > 0; j--)
            {
                num += (a[j]-'0')*jw;
                jw *= 10;
            }
            // cout<<"num = "<<num<<endl;
            return num;
        }
    }
}
int main()
{
    int ans,m,x,y;
    while(~scanf("%d",&n))
    {
        tot = 0;
        memset(head,-1,sizeof(head));
        for(int i = 0; i < n; i++)
        {
            scanf("%d",&x);
            char op[220];
            scanf("%s",op);
            int m = getnum(op);
            for(int j = 0; j < m; j++)
            {
                scanf("%d",&y);
                add_edge(x,y);
                add_edge(y,x);
            }
        }
        init();
        for(int i = 0; i < n; i++)
        {
            if(!dfn[i]) tarjan(i,-1);
        }
        sort(out,out+resnum,cmp);
        printf("%d critical links
",resnum);
        for(int i = 0; i < resnum; i++)
        {
            printf("%d - %d
",out[i].x,out[i].y);
        }
        puts("");
    }
    return 0;
}
原文地址:https://www.cnblogs.com/jifahu/p/5527589.html