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\n",ans);
    return 0;
}

 

posted @ 2017-02-13 16:48  神犇(shenben)  阅读(321)  评论(0编辑  收藏  举报