zoukankan      html  css  js  c++  java
  • Tarjan模板

    1.无向图求割点

    例题:P3388 【模板】割点(割顶)

    #include<queue>
    #include<cstring>
    #include<cstdio>
    #include<algorithm>
    #include<cmath>
    #include<iostream>
    using namespace std;
    typedef long long ll;
    const int maxm=200007;
    int n,m,ans;
    int pre[maxm],last[maxm],other[maxm],l;
    bool ge[maxm];
    int tot,dfn[maxm],low[maxm];
    void add(int x,int y)
    {
     l++;
     pre[l]=last[x];
     last[x]=l;
     other[l]=y;	
    }
    void dfs(int x,int fa)
    {
      dfn[x]=low[x]=++tot;
      int child=0;
      for(int p=last[x];p;p=pre[p])
      {
        int v=other[p];
        if(!dfn[v])
        {
          dfs(v,fa);
          low[x]=min(low[x],low[v]);
    	  if(dfn[x]<=low[v]&&x!=fa)
    	  ge[x]=1;
    	  if(x==fa)
    	  child++;	
        }
        else low[x]=min(low[x],dfn[v]);
      }
      if(x==fa&&child>=2)
      ge[x]=1;
    }
    int main()
    {
     scanf("%d%d",&n,&m);
     for(int i=1;i<=m;i++)
     {
       int x,y;
       scanf("%d%d",&x,&y);
       add(x,y);
       add(y,x);
     }
     for(int i=1;i<=n;i++)
     {
       if(!dfn[i])
       dfs(i,i);	
     }
     for(int i=1;i<=n;i++)
     if(ge[i]) ans++;
     printf("%d
    ",ans);
     for(int i=1;i<=n;i++)
     if(ge[i]) printf("%d ",i);
     return 0;	
    }
    

    2.有向图求强联通分量

    例题:受欢迎的牛

    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    int n,m;
    int pre[50005],last[10005],other[50005],l;
    int dfn[10005],low[10005],stack[10005],c[10005],ins[10005];
    int du[10005];
    int num;//搜索顺序 
    int top,cnt,ans[10005]; 
    void add(int x,int y)
    {
     l++;
     pre[l]=last[x];
     last[x]=l;
     other[l]=y;	
    }
    void tarjan(int x)
    {
      dfn[x]=low[x]=++num;
      stack[++top]=x;
      ins[x]=1;
      for(int p=last[x];p;p=pre[p])
      {
      	int v=other[p];
      	if(!dfn[v])
      	{
      		tarjan(v);
      		low[x]=min(low[x],low[v]);
      	}
      	else if(ins[v])
      	{
      	  low[x]=min(low[x],dfn[v]);	
      	}
      }
      if(dfn[x]==low[x])
      {
      	cnt++;
      	int y=0;
    	while(x!=y){
      	y=stack[top--],ins[y]=0;	
      	c[y]=cnt;
      	ans[cnt]++;
      	}
      }
    }
    int main()
    {
     scanf("%d%d",&n,&m);
     for(int i=1;i<=m;i++)
     {
       int x,y;
       scanf("%d%d",&x,&y);
       add(x,y);	
     }
     for(int i=1;i<=n;i++)
     {
     	if(!dfn[i]) tarjan(i);
     }
     for(int i=1;i<=n;i++)
     {
       for(int p=last[i];p;p=pre[p])
       {
         if(c[i]!=c[other[p]])
         {
         	du[c[i]]++;
         }
       }
     }
     int tt=0;
     for(int i=1;i<=cnt;i++)
     {
       if(!du[i])
       {
       	  if(tt)
       	  {
       	   printf("0
    ");
    		  return 0;	
       	  }
       	  tt=i;
       }
     }
     printf("%d
    ",ans[tt]);
     return 0;
    } 
    

    3.无向图求桥

    例题:炸铁路

    #include<queue>
    #include<cstring>
    #include<cstdio>
    #include<algorithm>
    #include<cmath>
    #include<iostream>
    using namespace std;
    typedef long long ll;
    const int maxm=10507;
    int n,m;
    int pre[maxm],last[maxm],other[maxm],l;
    int tot,dfn[maxm],low[maxm],cnt;
    struct node
    {
     int x,y;	
    }ans[maxm];
    bool cmp(node a,node b)
    {
     if(a.x==b.x) return a.y<b.y;
     return a.x<b.x;	
    }
    void add(int x,int y)
    {
     l++;
     pre[l]=last[x];	
     last[x]=l;
     other[l]=y;
    }
    void dfs(int x,int fa)
    {
     dfn[x]=low[x]=++tot;
     for(int p=last[x];p;p=pre[p])
     {
      int v=other[p];
      if(v==fa) continue;
      if(!dfn[v])
      {
        dfs(v,x);
    	low[x]=min(low[x],low[v]);
    	if(dfn[x]<low[v])
        {
           if(x>v) swap(x,v);
           ans[++cnt].x=x;
           ans[cnt].y=v;
        }
      }
      else low[x]=min(low[x],dfn[v]);
     }
    }
    int main()
    {
     scanf("%d%d",&n,&m);
     for(int i=1;i<=m;i++)
     {
      int x,y;
      scanf("%d%d",&x,&y);
      add(x,y);
      add(y,x);
     }
     for(int i=1;i<=n;i++)
     if(!dfn[i]) dfs(i,i);
     sort(ans+1,ans+cnt+1,cmp);
     for(int i=1;i<=cnt;i++)
     {
      	printf("%d %d
    ",ans[i].x,ans[i].y);
     }
     return 0;	
    }
    

    4.缩点

    #include<queue>
    #include<cstring>
    #include<cstdio>
    #include<algorithm>
    #include<cmath>
    #include<iostream>
    using namespace std;
    typedef long long ll;
    const int maxm=1e5+7;
    int n,m,ans;
    int w[maxm],val[maxm];
    int pre[maxm],last[maxm],other[maxm],l;
    int sta[maxm],vis[maxm],tot,dfn[maxm],low[maxm],from[maxm],dis[maxm];
    int ru[maxm];
    int id[maxm],top;
    queue<int> q;
    void add(int x,int y)
    {
     l++;
     from[l]=x;
     pre[l]=last[x];
     last[x]=l;
     other[l]=y;	
    }
    void dfs(int x)
    {
      dfn[x]=low[x]=++tot;
      sta[++top]=x;
      vis[x]=1;
      for(int p=last[x];p;p=pre[p])
      {
       	int v=other[p];
       	if(!dfn[v])
       	{
       	   dfs(v);
    	   low[x]=min(low[x],low[v]);	
       	}
       	else if(vis[v]) low[x]=min(low[x],dfn[v]);
      }
      if(dfn[x]==low[x])
      {
       int y=0;
       while(y!=x)
       {
        y=sta[top--];
        val[x]+=w[y];
        id[y]=x;
        vis[y]=0;
       }
      }
    }
    void solve()
    {
      for(int i=1;i<=n;i++)
      {
        if(id[i]==i&&!ru[i])
        {
    	 q.push(i);
    	 dis[i]=val[i];
       }
      }
      while(q.size())
      {
       int u=q.front();
       q.pop();
       for(int p=last[u];p;p=pre[p])
       {
       	 int v=other[p];
       	 dis[v]=max(dis[v],dis[u]+val[v]);
       	 ru[v]--;
       	 if(!ru[v]) q.push(v);
       }
      }
      ans=0;
      for(int i=1;i<=n;i++)
      ans=max(ans,dis[i]);
    }
    int main()
    {
     scanf("%d%d",&n,&m);
     for(int i=1;i<=n;i++)
     scanf("%d",w+i);
     for(int i=1;i<=m;i++)
     {
       int x,y;
       scanf("%d%d",&x,&y);
       add(x,y);	
     }
     for(int i=1;i<=n;i++)
     {
      if(!dfn[i])
      dfs(i);	
     }
     memset(last,0,sizeof(last));
     l=0;
     for(int i=1;i<=m;i++)
     {
       int x=id[from[i]],y=id[other[i]];
       if(x!=y)
       {
       	 add(x,y);
       	 ru[y]++;
       }
     }
     solve();
     printf("%d
    ",ans);
     return 0;	
    }
    
  • 相关阅读:
    Eclipse创建Python工程
    MySQL python安装
    pip安装-python2.7.15
    接口测试-HTTP重点知识及 测试工具
    接口测试-基础
    关闭win10的自动更新功能
    高版本MySQL(5.7,5.8)的JDBC连接新问题
    错误:java.sql.SQLException: Access denied for user ''@'localhost' (using password: NO)
    Idea SpringBoot工程提示 "Error running 'xxxx'": Command line is too long... 问题解决
    错误:23:36:21.161 [main] ERROR org.springframework.boot.SpringApplication
  • 原文地址:https://www.cnblogs.com/lihan123/p/11826338.html
Copyright © 2011-2022 走看看