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

时间:2023-03-10 04:56:00
刷题向》关于搜索+tarjan的奇怪组合题 BZOJ1194 (normal+)

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

  给出题目翻译:

  给你S张图,

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

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

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

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

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

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

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

Description

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

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

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)
  然后重点就没有啦。。。
  由于题目代码会较长,所以可以很好的考察代码能力。
愉快的贴出代码
 /**************************************************************
Problem: 1194
User: PencilWang
Language: C++
Result: Accepted
Time:4692 ms
Memory:2964 kb
****************************************************************/ #include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
int S,s,n,m,a,b;
bool Ff[],mp[][],f,F[][];
int stack[],T,low[],w[],ass,fa[],time[],mmp[][][],head[],point;
int pa,pb,headd[];
struct shit{
int aim,next,fro;
}e[][];
int cn;
void tarjan(int x)
{
time[x]=low[x]=++T;
Ff[stack[++ass]=x]=true;
for(int i=head[x];i;i=e[][i].next)
{
if(!time[e[][i].aim])
{
tarjan(e[][i].aim);
low[x]=min(low[x],low[e[][i].aim]);
}
else if(Ff[e[][i].aim])low[x]=min(low[x],time[e[][i].aim]);
}
if(time[x]==low[x])
{
Ff[x]=false;
w[fa[x]=++cn]=;
while(stack[ass]!=x)
{
w[fa[stack[ass]]=cn]++;
Ff[stack[ass--]]=false;
}
--ass;
}
}
void dfs(int x,int y)
{
if(F[x][y]||f)return ;
F[x][y]=true;
if(!mp[pa][x]&&mp[pb][y]){f=true;return ;}
dfs(mmp[pa][x][],mmp[pb][y][]);
dfs(mmp[pa][x][],mmp[pb][y][]); }
bool check()
{
memset(F,false,sizeof(F));
f=false;
dfs(,);
return !f;
}
void fuck(int x,int y)
{
e[][++point]=(shit){y,head[x],x};head[x]=point;
}
int cnt;
void rebuild()
{
for(int i=;i<=S;i++)
{
for(int j=head[i];j;j=e[][j].next)
if(fa[i]!=fa[e[][j].aim])
{
e[][++cnt].aim=fa[e[][j].aim];
e[][cnt].next=headd[fa[i]];
e[][cnt].fro=fa[i];
headd[fa[i]]=cnt;
}
}
}
int ans[];
int fi(int x)
{
if(ans[x])return ans[x];
ans[x]=w[x];
for(int i=headd[x];i;i=e[][i].next)
ans[x]=max(ans[x],fi(e[][i].aim)+w[x]);
return ans[x];
}
int find_ans()
{
int sb_1=;
for(int i=;i<=cn;i++)sb_1=max(sb_1,fi(i));
return sb_1;
}
int main()
{
scanf("%d",&S);
for(s=;s<=S;s++)
{
fa[s]=s;
scanf("%d%d",&n,&m);
for(int i=;i<=m;i++)
{
scanf("%d",&a);
mp[s][a+]=true;
}
for(int i=;i<=n;i++)
{
scanf("%d%d",&a,&b);
mmp[s][i][]=a+;mmp[s][i][]=b+;
}
}
for(int i=;i<=S;i++)
for(int j=;j<=S;j++)
{
if(j==i)continue;
pa=i;
pb=j;
if(check()){fuck(i,j);}
}
for(int i=;i<=S;i++)
if(!time[i])tarjan(i);
rebuild();
printf("%d",find_ans());
return ;
}

1194