• 刷题向》关于搜索+tarjan的奇怪组合题 BZOJ1194 (normal+)


      关于这道题,其实看懂了的话还是比较好写的,只是题目实在又臭又长,没有让人读下去的勇气。

      给出题目翻译:

      给你S张图,

      每张图有M个点,其中M个点中有N个是特殊单位,会给出。

      每个点又有0、1两条边指向其他点。

      这样我们每次从0这个点开始,选择向0或者向1走,是不是可以把路径表示成01串的形式捏?

      每次我们在模拟路径时,遇到特殊单位就会输出这串01串。

      那么图的包含关系定义为:A图输出的所有01串都可以在B中输出(即使是一样的图),这时就称B是A的亲爹;

      那么你的任务是找出图中最长的家族关系。

      当然不反对大家去看原题,祝大家平安

    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

     
      那么只要题看懂,恭喜你,这题你就A了一半了。
      由于极小的数据,所以判断亲爹的关系可以暴力搜索来解决(谁叫它数据小呢 doge脸)。
      然后我们可以把有父子关系的点连边,
      然后在图上找最长路就好了,但是由于这道题是允许有环的关系的,所以可以用tarjan缩个点。。。之后再暴搜一遍(doge脸*2)
      然后重点就没有啦。。。
      由于题目代码会较长,所以可以很好的考察代码能力。
    愉快的贴出代码
      1 /**************************************************************
      2     Problem: 1194
      3     User: PencilWang
      4     Language: C++
      5     Result: Accepted
      6     Time:4692 ms
      7     Memory:2964 kb
      8 ****************************************************************/
      9  
     10 #include<stdio.h>
     11 #include<string.h>
     12 #include<algorithm>
     13 using namespace std;
     14 int S,s,n,m,a,b;
     15 bool Ff[1000],mp[1000][1000],f,F[1000][1000];
     16 int stack[1000],T,low[1000],w[1000],ass,fa[1000],time[1000],mmp[100][100][2],head[3000],point;
     17 int pa,pb,headd[1000];
     18 struct shit{
     19 int aim,next,fro;
     20 }e[2][3000];
     21 int cn;
     22 void tarjan(int x)
     23 {
     24     time[x]=low[x]=++T;
     25     Ff[stack[++ass]=x]=true;
     26     for(int i=head[x];i;i=e[0][i].next)
     27     {
     28         if(!time[e[0][i].aim])
     29         {
     30         tarjan(e[0][i].aim);
     31         low[x]=min(low[x],low[e[0][i].aim]);
     32         }
     33         else if(Ff[e[0][i].aim])low[x]=min(low[x],time[e[0][i].aim]);
     34     }
     35     if(time[x]==low[x])
     36     {
     37         Ff[x]=false;
     38         w[fa[x]=++cn]=1;
     39         while(stack[ass]!=x)
     40         {
     41         w[fa[stack[ass]]=cn]++;
     42         Ff[stack[ass--]]=false;
     43         }
     44     --ass;
     45     }
     46 }
     47 void dfs(int x,int y)
     48 {
     49     if(F[x][y]||f)return ;
     50     F[x][y]=true;
     51     if(!mp[pa][x]&&mp[pb][y]){f=true;return ;}
     52     dfs(mmp[pa][x][1],mmp[pb][y][1]);
     53     dfs(mmp[pa][x][0],mmp[pb][y][0]);
     54  
     55 }
     56 bool check()
     57 {
     58     memset(F,false,sizeof(F));
     59     f=false;
     60     dfs(1,1);
     61     return !f;
     62 }
     63 void fuck(int x,int y)
     64 {
     65     e[0][++point]=(shit){y,head[x],x};head[x]=point;
     66 }
     67 int cnt;
     68 void rebuild()
     69 {
     70     for(int i=1;i<=S;i++)
     71     {
     72         for(int j=head[i];j;j=e[0][j].next)
     73         if(fa[i]!=fa[e[0][j].aim])
     74         {
     75         e[1][++cnt].aim=fa[e[0][j].aim];
     76         e[1][cnt].next=headd[fa[i]];
     77         e[1][cnt].fro=fa[i];
     78         headd[fa[i]]=cnt;
     79         }
     80     }
     81 }
     82 int ans[1000];
     83 int fi(int x)
     84 {
     85     if(ans[x])return ans[x];
     86     ans[x]=w[x];
     87     for(int i=headd[x];i;i=e[1][i].next)
     88     ans[x]=max(ans[x],fi(e[1][i].aim)+w[x]);
     89     return ans[x];
     90 }
     91 int find_ans()
     92 {
     93     int sb_1=0;
     94     for(int i=1;i<=cn;i++)sb_1=max(sb_1,fi(i));
     95     return sb_1;
     96 }
     97 int main()
     98 {
     99     scanf("%d",&S);
    100     for(s=1;s<=S;s++)
    101     {
    102     fa[s]=s;
    103     scanf("%d%d",&n,&m);
    104         for(int i=1;i<=m;i++)
    105         {
    106             scanf("%d",&a);
    107             mp[s][a+1]=true;
    108        }
    109         for(int i=1;i<=n;i++)
    110         {
    111             scanf("%d%d",&a,&b);
    112             mmp[s][i][0]=a+1;mmp[s][i][1]=b+1;
    113         }
    114     }
    115     for(int i=1;i<=S;i++)
    116         for(int j=1;j<=S;j++)
    117         {
    118         if(j==i)continue;
    119         pa=i;
    120         pb=j;
    121         if(check()){fuck(i,j);}
    122         }
    123     for(int i=1;i<=S;i++)
    124     if(!time[i])tarjan(i);
    125     rebuild();
    126     printf("%d",find_ans());
    127     return 0;
    128 }
    1194
  • 相关阅读:
    使用PeopleSoft 异步操作设置步骤
    如何在Oracle数据库中查看哪些用户在执行哪些SQL
    PeopleSoft单点登录工作原理
    登录PeopleTools 提示ora-00942表视图不存在 select xxx from sysadm.psoprdefn
    比较完整的PeopleSoft工具表名
    如何查看一台服务器是虚拟服务器还是物理机
    Vue H5 History 部署IIS上404问题
    asp.net core 3.0中webapi post请求返回http 400
    目前流行前端几大UI框架
    entity-framework-core – 实体框架核心RC2表名称复数
  • 原文地址:https://www.cnblogs.com/PencilWang/p/5951120.html
Copyright © 2020-2023  润新知