zoukankan      html  css  js  c++  java
  • [HNOI2006]潘多拉的宝盒

    https://www.zybuluo.com/ysner/note/1250303

    题面

    给定(s)个自动机,如果某个自动机(A)能产生的所有串都能在自动机(B)中产生(即走相同(0/1)路径后,同时碰到输出元),则称(B)(A)的一个升级,求最长升级序列长度。

    • (s,nleq50)

    解析

    辣鸡题目考语文
    然而看懂题后还是很简单的。
    判断(B)是否为(A)的升级,就每次分别在(A,B)走相同的(0/1)路径(因每个点有两个出度),若在(A)碰到一个输出元,而此时(B)没有,就说明不是升级。
    是升级就把(A->B)边权赋为(1)
    最后(Floyd)跑最长路即可。
    (或者建边+拓扑排序也可以)。

    但要注意,如果有两个完全相同的自动机,两者都会判为对方的升级,这时需强制只有一个方向边权赋为(1)(建边的话跑(Tarjan)缩点)。
    没清空queue调了?h

    // luogu-judger-enable-o2
    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<queue>
    #define ll long long
    #define re register
    #define il inline
    #define max(a,b) ((a)>(b)?(a):(b))
    #define min(a,b) ((a)<(b)?(a);(b))
    #define N 100
    #define fp(i,a,b) for(re int i=a;i<=b;i++)
    #define fq(i,a,b) for(re int i=a;i>=b;i--)
    using namespace std;
    int s,n,m,h[N],out[N][N],a[N][N][2],dis[N][N];
    ll ans;
    bool vis[N][N];
    struct node{int x,y;};
    queue<node>Q;
    il int gi()
    {
        re int x=0,t=1;
        re char ch=getchar();
        while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
        if(ch=='-') t=-1,ch=getchar();
        while(ch>='0'&&ch<='9') x=x*10+ch-48,ch=getchar();
        return x*t;
    }
    il int check(re int s1,re int s2)
    {
      //printf("!!!%d %d
    ",s1,s2);
      while(!Q.empty()) Q.pop();
        memset(vis,0,sizeof(vis));
        Q.push((node){1,1});
        while(!Q.empty())
        {
            re node now=Q.front(),tmp;Q.pop();//gg
        if(out[s1][now.x]&&!out[s2][now.y]) return 0;
          tmp.x=a[s1][now.x][0];tmp.y=a[s2][now.y][0];
      	if(!vis[tmp.x][tmp.y]) vis[tmp.x][tmp.y]=1,Q.push(tmp);
            tmp.x=a[s1][now.x][1];tmp.y=a[s2][now.y][1];
      	if(!vis[tmp.x][tmp.y]) vis[tmp.x][tmp.y]=1,Q.push(tmp);
        }
        return 1;
    }
    int main()
    {
        s=gi();
        fp(i,1,s)
        {
            n=gi();m=gi();
        //fp(j,1,n) a[i][j][0]=a[i][j][1]=1;
            fp(j,1,m) out[i][gi()+1]=1;
            fp(j,1,n)
            {
                re int u=gi()+1,v=gi()+1;
                a[i][j][0]=u;a[i][j][1]=v;
            }
        }
        memset(dis,-63,sizeof(dis));
        fp(i,1,s)
            fp(j,1,s)
          if(i!=j&&check(i,j)&&dis[j][i]<0) dis[i][j]=1;//注意到有完全相同的自动机
        //fp(i,1,s) fp(j,1,s) printf("%d %d %d
    ",i,j,dis[i][j]);
        fp(k,1,s)
            fp(i,1,s)
          fp(j,1,s)
          //if(dis[i][j]<dis[i][k]+dis[k][j]&&dis[i][k]&&dis[k][j]
            dis[i][j]=max(dis[i][j],dis[i][k]+dis[k][j]),ans=max(ans,dis[i][j]);
        printf("%lld
    ",ans+1);
        return 0;
    }
    
  • 相关阅读:
    程序员修炼之道阅读笔记02
    第十五周课堂练习-查找最长单词链
    文件读写总结
    第十五周
    暑假总结1
    软件工程课程总结
    第十六周总结
    用户场景分析
    学期课后个人总结
    第十五周总结
  • 原文地址:https://www.cnblogs.com/yanshannan/p/9479390.html
Copyright © 2011-2022 走看看