• 1194: [HNOI2006]潘多拉的盒子


    1194: [HNOI2006]潘多拉的盒子

    Time Limit: 10 Sec  Memory Limit: 162 MB
    Submit: 464  Solved: 221
    [Submit][Status][Discuss]

    Description

     

    Input

    第一行是一个正整数S,表示宝盒上咒语机的个数,(1≤S≤50)。文件以下分为S块,每一块描述一个咒语机,按照咒语机0,咒语机1„„咒语机S-1的顺序描述。每一块的格式如下。 一块的第一行有两个正整数n,m。分别表示该咒语机中元件的个数、咒语源输出元的个数(1≤m≤n≤50)。 接下来一行有m个数,表示m个咒语源输出元的标号(都在0到n-1之间)。接下来有n行,每一行两个数。第i行(0≤i≤n-1)的两个数表示pi,0和pi,1(当然,都在0到n-1之间)。

    Output

    第一行有一个正整数t,表示最长升级序列的长度。

    Sample Input

    4
    1 1
    0
    0 0
    2 1
    0
    1 1
    0 0
    3 1
    0
    1 1
    2 2
    0 0
    4 1
    0
    1 1
    2 2
    3 3
    0 0

    Sample Output

    3

    HINT

     

    Source

    分析:

      思路比较简单:对于每对i,j,如果满足i能产生的所有字符串j都能产生,则建边,跑最长路。
    但是图可能不是DAG,所以要先预处理缩点,然后再做。

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    using namespace std;
    const int N=55;
    struct data{int danger[N],lc[N],rc[N];}T[N];
    struct edge{int v,next;}e[N*N*2],e2[N*N*2];
    int S,ans,a,b,tot,head[N],tot2,head2[N];bool flag,vis[N][N];
    int dfs_cnt,scc_cnt,top,dfn[N],low[N],num[N],sccno[N],stack[N],dp[N];
    void add(int x,int y){
        e[++tot].v=y;e[tot].next=head[x];head[x]=tot;
    }
    void add2(int x,int y){
        e2[++tot2].v=y;e2[tot2].next=head2[x];head2[x]=tot2;
    }
    void dfs_contain(int x,int y){
        if(vis[x][y]||flag) return ;
        vis[x][y]=1;
        if(T[b].danger[y]&&!T[a].danger[x]){flag=1;return ;}
        dfs_contain(T[a].lc[x],T[b].lc[y]);
        dfs_contain(T[a].rc[x],T[b].rc[y]);
    }
    bool check(int x,int y){
        flag=0;a=x;b=y;
        memset(vis,0,sizeof vis);
        dfs_contain(1,1);
        return !flag;
    }
    void tarjan(int u){
        dfn[u]=low[u]=++dfs_cnt;
        stack[++top]=u;
        for(int i=head[u];i;i=e[i].next){
            int v=e[i].v;
            if(!dfn[v]){
                tarjan(v);
                low[u]=min(low[u],dfn[v]);
            }
            else if(!sccno[v]){
                low[u]=min(low[u],low[v]);
            }
        }
        if(low[u]==dfn[u]){
            scc_cnt++;
            for(int x;;){
                x=stack[top--];
                sccno[x]=scc_cnt;
                num[scc_cnt]++;//WA*2
                if(x==u) break;
            }
        }
    }
    int get_cnt(int x){
        if(dp[x]) return dp[x];
        int maxn=num[x];//WA*1
        for(int i=head2[x];i;i=e2[i].next){
            maxn=max(maxn,dp[e2[i].v]+num[x]);
        }
        return dp[x]=maxn;
    }
    int main(){
        scanf("%d",&S);
        for(int k=1,n,m,x,y;k<=S;k++){
            scanf("%d%d",&n,&m);
            while(m--) scanf("%d",&x),T[k].danger[x+1]=1;
            for(int i=1;i<=n;i++){
                scanf("%d%d",&x,&y);
                T[k].lc[i]=x+1;
                T[k].rc[i]=y+1;
            }
        }
        for(int i=1;i<=S;i++){
            for(int j=1;j<=S;j++){
                if(i==j) continue;
                if(check(i,j)) add(i,j);
            }
        }
        for(int i=1;i<=S;i++) if(!dfn[i]) tarjan(i);
        for(int i=1;i<=S;i++){
            for(int j=head[i];j;j=e[j].next){
                if(sccno[i]!=sccno[e[j].v]) add2(sccno[i],sccno[e[j].v]);
            }
        }
        for(int i=1;i<=scc_cnt;i++) ans=max(ans,get_cnt(i));
        printf("%d
    ",ans);
        return 0;
    }
  • 相关阅读:
    [cf1217F]Forced Online Queries Problem
    [cf1215F]Radio Stations
    超级楼梯[HDU2041]
    亲和数[HDU2040]
    三角形[HDU2039]
    今年暑假不AC[HDU2037]
    Counting Squares[HDU1264]
    CodeForces Round 195 Div2
    Square Coins[HDU1398]
    The number of divisors(约数) about Humble Numbers[HDU1492]
  • 原文地址:https://www.cnblogs.com/shenben/p/6394489.html
Copyright © 2020-2023  润新知