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

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了刷题向》关于搜索+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

 

以上是关于刷题向》关于搜索+tarjan的奇怪组合题 BZOJ1194 (normal+)的主要内容,如果未能解决你的问题,请参考以下文章

刷题向》关于第一篇状压DP BZOJ1087 (EASY+)

刷题向》一道关于位运算的神题(BZOJ3668)(HARD)

刷题向》关于一道比较优秀的递推型DP(openjudge9275)(EASY+)

刷题向》关于线段树的区间开根号 BZOJ3211

刷题向》关于一道像差分约束的数学题BZOJ1045

LeetCode刷题模版:31 - 40