zoukankan      html  css  js  c++  java
  • BZOJ4267 : 小强的颜色

    首先剔除$1$号心情不能到达的无用心情,然后采用分割法进行DFA的最小化。

    每次遍历所有集合,将集合中和集合中第一个心情行为或者转移所在集合不同的心情放入新集合中。

    最后按字典序依次给每个集合编号即可。

    因为最多$O(N)$次分离,每次遍历时间复杂度为$O(NP)$。

    故总时间复杂度为$O(N^2P)$。

    #include<cstdio>
    const int N=1010;
    int p,m,n,i,j,k,x,a[N][30],cnt,len[N],g[N][N],pos[N],id[N],q[N],all;bool vis[N],flag;
    inline bool equal(int x,int y){
      if(a[x][0]!=a[y][0])return 0;
      for(int i=1;i<=p;i++)if(pos[a[x][i]]!=pos[a[y][i]])return 0;
      return 1;
    }
    void dfs(int x){
      if(vis[x])return;
      vis[x]=1;
      g[1][++len[1]]=x;
      for(int i=1;i<=p;i++)dfs(a[x][i]);
    }
    int main(){
      scanf("%d%d%d",&p,&m,&n);
      for(i=1;i<=n;i++)for(j=1;j<=p;j++)scanf("%d",&a[i][j]);
      for(i=1;i<=n;i++)scanf("%d",&a[i][0]);
      dfs(cnt=1);
      while(1){
        flag=0;
        for(i=1;i<=cnt;i++)for(j=1;j<=len[i];j++)pos[g[i][j]]=i;
        for(i=1;i<=cnt;i++)if(len[i]>1){
          for(j=2;j<=len[i];j++)if(!equal(g[i][1],g[i][j]))break;
          if(j>len[i])continue;
          cnt++,k=1;
          for(j=2;j<=len[i];j++)if(!equal(g[i][1],g[i][j]))g[cnt][++len[cnt]]=g[i][j];
          else g[i][++k]=g[i][j];
          len[i]=k;
          flag=1;
          break;
        }
        if(!flag)break;
      }
      printf("%d
    ",cnt);
      id[1]=q[1]=all=1;
      for(i=1;i<=cnt;i++){
        x=g[q[i]][1];
        for(j=1;j<=p;j++){
          k=pos[a[x][j]];
          if(!id[k])q[id[k]=++all]=k;
          printf("%d%c",id[k],j<p?' ':'
    ');
        }
      }
      for(i=1;i<=cnt;i++)printf("%d%c",a[g[q[i]][1]][0],i<cnt?' ':'
    ');
      return 0;
    }
    

      

  • 相关阅读:
    Sqlite && EF Code FIRST 终极解决方案 2019.5.17
    网卡 API 相关
    (依赖注入框架:Ninject ) 一 手写依赖注入
    Nlog 日志框架简单教程
    调试时候输出信息到输出窗口
    利用VS 性能探查器 解决代码性能不高问题
    Image 释放
    记一次数据丢失(电脑硬盘closed to down)的经历
    [极短]数字求和
    在博客园中使用pixijs
  • 原文地址:https://www.cnblogs.com/clrs97/p/8506485.html
Copyright © 2011-2022 走看看