zoukankan      html  css  js  c++  java
  • ZOJ Problem

      题意:求无向图的割边。

      思路: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
    ",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("
    ");
            }
            if(t)
                puts("");
        }
        return 0;
    }
  • 相关阅读:
    有用的sql语句积累
    spring boot sso 学习资源
    notepad++ 常用快捷键
    artTemplate的使用总结
    ajax完整请求
    03 Mybatis框架---学习笔记1--框架的概念及优势
    02 Struts2框架----学习笔记2(了解一下,已过时)
    IDEA 获取类的相对路径和绝对路径
    01 Struts2框架学习(了解一下,已过时)
    喜马拉雅 FM 已购付费音频下载
  • 原文地址:https://www.cnblogs.com/jifahu/p/5506329.html
Copyright © 2011-2022 走看看