15145641

  题意:求无向图的割边。

  思路:tarjan算法求割边,访问到一个点,如果这个点的low值比它的dfn值大,它就是割边,直接ans++(之所以可以直接ans++,是因为他与割点不同,每条边只访问了一遍)。

  需要注意的就是此处有多重边,题目中要求输出确定的不能被删除的边,而多重边的保留不是可以确定的,所以多重边都是不可以被保留的,我们可以在邻接表做一个flag的标记,判断他是不是多重边。

  注意建图的时候数组应该是m × 2,因为这里是无向边,当心RE!

  注意输出的时候编号是必须要拍好序再输出。

  还有一个地方需要注意的就是应该选择高效的建图方式,我一开始看见给了5秒,就用邻接矩阵建了图,毕竟他能很好的记录重边,但交上去并不好使。。。又换了vector,结果莫名其妙的程序崩溃,我都开始怀疑人生了,想到zoj一向以严格***钻出名,干脆换了比较高效的链式前向星,总算是过了,下面是代码:

  后来的补充~  

这个后来尚尚告诉我判断边是否出现过可以用这种方法:图中最多有N个点,可以用map解决这个问题,把x和y这两个边压缩成一个整数10*N*X + Y,用map记录下这个数是否出现过,就是这条边有没有出现过.这种方法跑了800ms,我的那种方法跑了1000+ms,看来还是遍历的方式太蠢了,建议读者使用建议方式,如果卡时间也不怕了

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define maxn 10010
int head[maxn],tot,dfn[maxn],low[maxn],ans_id[maxn*10],ans,cnt;
struct EDGE
{
    int to,nxt,flag,id;
} edge[maxn*20];
void add_edge(int x,int y,int id)
{
    bool mark = true;
    int pos = 0;
    for(int i = head[x]; i != -1; i = edge[i].nxt)
    {
        if(edge[i].to == y)
        {
            mark = false;
            pos = i;
            break;
        }
    }
    if(!mark)
    {
        edge[pos].flag = 1;
        return;
    }
    edge[cnt].to = y;
    edge[cnt].nxt = head[x];
    edge[cnt].flag = 0;
    edge[cnt].id = id;
    head[x] = cnt++;
}
void tarjan(int x,int fa)
{
    dfn[x] = low[x] = ++tot;
    for(int i = head[x]; i != -1; i = edge[i].nxt)
    {
        int y = edge[i].to;
        if(!dfn[y])
        {
            tarjan(y,x);
            low[x] = min(low[x],low[y]);
            if(low[y] > dfn[x] && !edge[i].flag)///判断重边
            {
                ans_id[ans++] = edge[i].id;
            }
        }
        else if(y != fa)
            low[x] = min(low[x],dfn[y]);
    }
    return;
}
int main()
{
    int t,n,m;
    scanf("%d",&t);
    while(t--)
    {
        cnt = 0,tot = 0,ans = 0;
        memset(head,-1,sizeof(head));
        scanf("%d%d",&n,&m);
        for(int i = 1; i <= m; i++)
        {
            int x,y;
            scanf("%d%d",&x,&y);
            add_edge(x,y,i);
            add_edge(y,x,i);
        }
        memset(dfn,0,sizeof(dfn));
        memset(low,0,sizeof(low));
        tarjan(1,-1);
        printf("%d\n",ans);
        sort(ans_id,ans_id + ans);
        if(ans != 0)
        {
            for(int i = 0; i < ans; i++)
            {
                i == 0 ? printf("%d",ans_id[i]) : printf(" %d",ans_id[i]);
            }
            printf("\n");
        }
        if(t)
            puts("");
    }
    return 0;
}

 

posted on 2016-05-18 19:32  icode-xiaohu  阅读(290)  评论(0编辑  收藏  举报