• ZOJ3795 Grouping(强连通分量+缩点+记忆化搜索)


    题目给一张有向图,要把点分组,问最少要几个组使得同组内的任意两点不连通。

    首先考虑找出强连通分量缩点后形成DAG,强连通分量内的点肯定各自一组,两个强连通分量的拓扑序能确定的也得各自一组。

    能在同一组的就是两个强连通分量在不同的从入度0到出度0的强连通分量的路径上。

    那么算法很直观就能想到了,用记忆化搜索,d[u]表示从强连通分量u出发到出度为0的强连通分量最少要几个组(最多有几个点)。

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 using namespace std;
     5 #define MAXN 110000
     6 #define MAXM 330000
     7 struct Edge{
     8     int u,v,next;
     9 }edge[MAXM];
    10 int head[MAXN],NE;
    11 void addEdge(int u,int v){
    12     edge[NE].u=u; edge[NE].v=v; edge[NE].next=head[u];
    13     head[u]=NE++;
    14 }
    15 int bn,belong[MAXN],size[MAXN];
    16 int dn,dfn[MAXN],low[MAXN];
    17 int top,stack[MAXN]; bool instack[MAXN];
    18 void tarjan(int u){
    19     dfn[u]=low[u]=++dn;
    20     stack[++top]=u; instack[u]=1;
    21     for(int i=head[u]; i!=-1; i=edge[i].next){
    22         int v=edge[i].v;
    23         if(dfn[v]==0){
    24             tarjan(v);
    25             low[u]=min(low[u],low[v]);
    26         }else if(instack[v]){
    27             low[u]=min(low[u],dfn[v]);
    28         }
    29     }
    30     if(dfn[u]==low[u]){
    31         int v; ++bn;
    32         do{
    33             v=stack[top--];
    34             instack[v]=0;
    35             belong[v]=bn; ++size[bn];
    36         }while(u!=v);
    37     }
    38 }
    39 int d[MAXN];
    40 int dfs(int u){
    41     if(d[u]) return d[u];
    42     int res=0;
    43     for(int i=head[u]; i!=-1; i=edge[i].next){
    44         int v=edge[i].v;
    45         res=max(res,dfs(v));
    46     }
    47     return d[u]=res+size[u];
    48 }
    49 int main(){
    50     int n,m,a,b;
    51     while(~scanf("%d%d",&n,&m)){
    52         NE=0;
    53         memset(head,-1,sizeof(head));
    54         while(m--){
    55             scanf("%d%d",&a,&b);
    56             addEdge(a,b);
    57         }
    58         top=dn=bn=0;
    59         memset(dfn,0,sizeof(dfn));
    60         memset(instack,0,sizeof(instack));
    61         memset(size,0,sizeof(size));
    62         for(int i=1; i<=n; ++i){
    63             if(dfn[i]==0) tarjan(i);
    64         }
    65         
    66         int tmp=NE; NE=0;
    67         memset(head,-1,sizeof(head));
    68         for(int i=0; i<tmp; ++i){
    69             int u=belong[edge[i].u],v=belong[edge[i].v];
    70             if(u==v) continue;
    71             addEdge(u,v);
    72         }
    73         memset(d,0,sizeof(d));
    74         int res=0;
    75         for(int i=1; i<=bn; ++i){
    76             res=max(res,dfs(i));
    77         }
    78         printf("%d
    ",res);
    79     }
    80     return 0;
    81 }
  • 相关阅读:
    C# DataGridView的使用
    C# DataTable使用方法详解
    .NET 异步 Task的一些摘抄记录
    mybatis源码分析之调用过程
    Uipath学习(6):Uipath使用Outlook邮箱
    ABAP学习(33):Selection Screen的Search Help
    Uipath学习(5):Application及Browser,数据获取
    Web Dynpro for ABAP(1):Web Dynpro结构
    Uipath学习(4):Uipath操作excel
    Web Dynpro for ABAP(2):Basic & Dynamic Programmings
  • 原文地址:https://www.cnblogs.com/WABoss/p/5184989.html
Copyright © 2020-2023  润新知