• 找环


    圆方树:https://www.cnblogs.com/cjyyb/p/9098400.html

    1.点双连通分量

    找到了一个新的不错的模板

    void dfs(int x,int y)
    {
        dfn[x]=low[x]=++cnt;
        int ch=0;
        for (rint u=head[x];u;u=e[u].a)
        {
            int v=e[u].b;
            if (v==y) continue;
            if (!dfn[v])
            {
                st[++top2]=v;
                dfs(v,x);
                if (low[v]>=dfn[x])
                {
                    iscut[x]=1;
                    bcc[++cnt3].clear();
                    do{
                        bcc[cnt3].push_back(st[top2]);
                    }while (st[top2--]!=v);
                    bcc[cnt3].push_back(x);
                }
                if (low[v]<low[x]) low[x]=low[v];
            }
            if (dfn[v]<low[x]) low[x]=dfn[v];
        }
        if (x==1&&ch<=1) iscut[1]=0;
    }

    缩点双的缩法是 把除割点以外的点双缩一起,割点单独

    因为两点之间可能有多条边 所以要用并查集维护

    2.边双连通分量

    缩完之后两个块之间一定只有一条边(不然就是1个边双了)

    #include <cstdio>
    #include <iostream>
    #include <algorithm>
    #include <stack>
    #include <cmath>
    #include <cstring>
    using namespace std;
    #define rint register int
    #define IL inline
    #define rep(i,h,t) for (int i=h;i<=t;i++)
    #define dep(i,t,h) for (int i=t;i>=h;i--)
    #define me(x) memset(x,0,sizeof(x))
    const int N=1e5;
    int n,m,head[N],l,cnt,scc_cnt,scc[N],f[N],dfn[N],low[N];
    bool vis[N];
    struct re{
      int a,b;
    }e[N*2],jl[N];
    stack<int> S;
    void arr(int x,int y)
    {
      e[++l].a=head[x];
      e[l].b=y;
      head[x]=l;
    }
    void dfs(int x,int y)
    {
      S.push(x);
      dfn[x]=low[x]=++cnt;
      for (rint u=head[x];u;u=e[u].a)
      {
        rint v=e[u].b;
        if (v!=y)
        {
          if (!dfn[v])
          {
            dfs(v,x);
            low[x]=min(low[x],low[v]);
          }
          low[x]=min(low[x],dfn[v]);
        }
      }
      if (low[x]==dfn[x])
      {
        scc_cnt++;
        while (1)
        {
          int v=S.top(); S.pop();
          scc[v]=scc_cnt;
          if (v==x) break;
        }
      }
    }
    int main()
    {
      freopen("1.in","r",stdin);
      freopen("1.out","w",stdout);
      ios::sync_with_stdio(false);
      while (cin>>n>>m)
      {
        l=0; me(head); me(f); cnt=0; scc_cnt=0;
        int x,y;
        rep(i,1,m)
        {
          cin>>x>>y;
          arr(x,y); arr(y,x);
          jl[i].a=x; jl[i].b=y;
        }
        rep(i,1,n) if (!vis[i]) dfs(i,0);
        rep(i,1,m) 
          if (scc[jl[i].a]!=scc[jl[i].b])
            f[scc[jl[i].a]]++,f[scc[jl[i].b]]++;
        int ans=0;
        rep(i,1,n) if (f[i]==1) ans++;
        cout<<(ans+1)/2<<endl;
      }
      return 0;
    }

    3.强连通分量

    4.仙人掌图找环

    void find(ll x,ll y)
    {
        do
        {
            st1[++top]=x;
            st2[top]=faqz[x];
            belong[x]=1;
            if (x==y) break;
            x=fa[x];
        }while (1);
    }
    void dfs(ll x,ll y)
    {
        dfn[x]=low[x]=++cnt; fa[x]=y;
        for (rint u=head[x];u;u=e[u].a)
        {
            rint v=e[u].b;
            if (v==y) continue;
            faqz[v]=e[u].c;
            if (!dfn[v]) dfs(v,x);
            if (dfn[v]<dfn[x])
            {
                find(x,v);
            }
        }
    }

    这么写就可以啦 很简单

    5.判断一张图是不是仙人掌

    无向图:poj 2793

    有向图:hdu 3594

    6.造一张仙人掌图

    比较暴力的做法就随机的树(高度比较低)

    然后随机两个点,看这之间的点是不是都没被覆盖

  • 相关阅读:
    dos cmd重启2003命令shutdown -r -t 0
    asp的RegExp对象正则表达式功能用法
    sql查询百分号的方法
    tabbar颜色与文字大小,状态栏样式
    打印所有系统字体名字,创建可拉伸图片,获取文字长度
    判断推送权限是否开启
    mac xcode 快捷键
    一个view相对于屏幕或者另外一个view 的坐标
    swift 2 选择头像图片
    scrapyd在window上的部署
  • 原文地址:https://www.cnblogs.com/yinwuxiao/p/9813811.html
Copyright © 2020-2023  润新知