• poj 3694 Network 夜


    http://poj.org/problem?id=3694

    用了Tarjan bfs 缩点

    所以时间复杂度比较高

    思路 先建双向图 重边要处理(用一个变量表示边数)

    用Tarjan算法缩点

    重新建了一个缩点后的双向图

    增加边时用bfs 搜索路径上的桥如果还有就对数量进行操作并将此桥标记为没有

    每次重复

    #include<iostream>
    #include<cstring>
    #include<stack>
    #include<cstdio>
    #include<queue>
    
    using namespace std;
    
    const int N=100005;
    struct node
    {
        struct tt *next;
    }mem[N];//原图
    struct nodeq
    {
        struct ttq *next;
    }memq[N];
    struct tt
    {
        struct tt *next;
        int j;
        int k;
    };
    struct ttq
    {
        struct ttq *next;
        int j;
        bool bridge;//此桥是否存在
    };//缩点后的图
    void build(int i,int j)
    {
        struct tt *t;
        t=mem[i].next;
        while(t!=NULL)
        {
            if(t->j==j)
            {
                ++t->k;//记录此路的数量
                return ;
            }
            t=t->next;
        }
        t=new tt;
        t->j=j;
        t->k=1;
        t->next=mem[i].next;
        mem[i].next=t;
    }
    bool in[N];
    int low[N];
    int dfn[N];
    stack<int>str;
    int time;
    bool visited[N];
    int uppoint[N];//缩点数组
    int f[N];
    int l,r;
    int ans;
    void Clear(int n)
    {
        for(int i=1;i<=n;++i)
        {mem[i].next=NULL;memq[i].next=NULL;}
    }
    void Tarjan(int pre,int k,int x)
    {
        ++time;
        visited[x]=true;
        in[x]=true;
        dfn[x]=low[x]=time;
        str.push(x);
        struct tt *t=mem[x].next;
        while(t!=NULL)
        {
            if(visited[t->j]==false)
            {
                Tarjan(x,t->k,t->j);
                low[x]=min(low[x],low[t->j]);
            }
            else if(in[t->j]==true&&(pre!=t->j||(pre==t->j&&k>1)))//如果搜到上一个点则必须是不只一条路
            {
                low[x]=min(low[x],dfn[t->j]);
            }
            t=t->next;
        }
        if(low[x]==dfn[x])
        {
            while(str.top()!=x)
            {
                uppoint[str.top()]=x;//缩点 全缩成x
                in[str.top()]=false;
                str.pop();
            }
           uppoint[x]=x;
           in[str.top()]=false;
           str.pop();
        }
    }
    void buildtree(int i,int j)//建新图
    {
        struct ttq *t=new ttq;
        t->j=j;
        t->bridge=true;//初始化存在
        t->next=memq[i].next;
        memq[i].next=t;
    }
    void dfs(int x)
    {
        visited[x]=true;
        struct tt *t=mem[x].next;
        while(t!=NULL)
        {
            if(!visited[t->j])
            {
                if(uppoint[x]!=uppoint[t->j])
                {
                    ++ans;
                    buildtree(uppoint[x],uppoint[t->j]);//双向
                    buildtree(uppoint[t->j],uppoint[x]);//双向
                }
                dfs(t->j);
            }
            t=t->next;
        }
    }
    void rebuild()
    {
        memset(visited,false,sizeof(visited));
        dfs(1);
    }
    int dec(int st,int nd)
    {
        queue<int>str;
        memset(visited,false,sizeof(visited));
        str.push(st);
        f[st]=st;
        visited[st]=true;
        struct ttq *t;
        while(1)//bfs 找两点路径
        {
            int x=str.front();
            if(x==nd){break;}
            str.pop();
            t=memq[x].next;
            while(t!=NULL)
            {
                if(!visited[t->j])
                {
                    visited[t->j]=true;
                    f[t->j]=x;
                    str.push(t->j);
                }
                t=t->next;
            }
        }
        int k=nd;
        int num=0;
        while(k!=st)
        {
            int pre=f[k];
            t=memq[pre].next;
            while(t!=NULL)
            {
                if(t->j==k)
                {
                   if(t->bridge==true)
                   {
                       ++num;t->bridge=false;//如果此桥存在 则计数并标记
                   }
                   break;
                }
                t=t->next;
            }
            t=memq[k].next;
            while(t!=NULL)//反向的也要
            {
                if(t->j==pre)
                {
                   if(t->bridge==true)
                   {
                       ++num;t->bridge=false;
                   }
                   break;
                }
                t=t->next;
            }
            k=pre;
        }
        return num/2;//正向加反向的 所以要除2
    }
    int main()
    {
        int n,m;
        for(int w=1;;++w)
        {
            scanf("%d %d",&n,&m);
            if(n==0&&m==0)
            break;
            while(m--)
            {
                int i,j;
                scanf("%d %d",&i,&j);
                build(i,j);
                build(j,i);
            }
            memset(in,false,sizeof(in));
            memset(visited,false,sizeof(visited));
            while(!str.empty())
            str.pop();
            time=0;
            Tarjan(1,1,1);
            ans=0;
            rebuild();
            int q;
            scanf("%d",&q);
            printf("Case %d:\n",w);
            while(q--)
            {
                scanf("%d %d",&l,&r);
                l=uppoint[l];r=uppoint[r];
                if(ans!=0&&l!=r)
                {
                    ans-=dec(l,r);
                }
                printf("%d\n",ans);
            }
            printf("\n");
            Clear(n);
        }
        return 0;
    }
    
    
    
  • 相关阅读:
    ELK的学习与应用
    windows 常用命令
    Electron笔记
    C#基础
    IIS运行NetCore程序
    nuget打包
    web pack备忘
    基于并发订课系统的架构演变
    面试造核弹的童话
    Python3-接口自动化-11-使用join方法请求参数拼接,格式key1=value1&keys=value2....
  • 原文地址:https://www.cnblogs.com/liulangye/p/2527031.html
Copyright © 2020-2023  润新知