刷题向》关于搜索+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

时间: 2024-12-22 22:59:57

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

(莫队算法)两题莫队算法统计数量的入门题

因为这两题差不多,而且比较简单,就放一起,做了这题,这种题目就是巨水的题了.随便写都行. CodeForces - 86D  Powerful array 题意: 多次查询数列中从L到R每个数字出现次数的平方乘这个数字的和. 代码: 1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <cmath> 5 #include <map> 6 #includ

【刷题】【搜索】新数独

很暴力的搜索,还没有什么剪枝...... 心得: [1]如果只查询和修改,用bool比bitset快 [2]rnt在循环中会比int快 [3]减少简单的函数调用 #include<cstdio> #include<cstdlib> #include<bitset> #include<iostream> #define rnt register int using namespace std; int ans[10][10]; char mp[2][10][1

刷LeetCode的正确姿势——第1、125题

最近刷LeetCode比较频繁,就购买了官方的参考电子书 (CleanCodeHandbook),里面有题目的解析和范例源代码,可以省去非常多寻找免费经验分享内容和整理这些资料的时间.惊喜的是,里面的所有源代码都是用java语言写的. 接下来的一段时间里,我会将里面的大部分内容翻译成中文,再加上一些小y自己的解法和扩展内容,以博客的形式发在博客园.我想,这会是一件非常有趣的事情. 以下是翻译的前言部分,第1.4题以及其解析部分. 前言: 嗨,各位刷LeetCode的小伙伴们. 就像你们看到这本书

poj1144 tarjan求割点 裸题

Network Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 11684   Accepted: 5422 Description A Telephone Line Company (TLC) is establishing a new telephone cable network. They are connecting several places numbered by integers from 1 to N

[华为机试真题]66.单词搜索

题目 代码 /*--------------------------------------- * 日期:2015-07-06 * 作者:SJF0115 * 题目:WordSearch * 来源:华为机试真题 -----------------------------------------*/ #include <iostream> #include <string> #include <vector> #include <stack> #include

集训第五周动态规划 I题 记忆化搜索

Description Michael喜欢滑雪百这并不奇怪, 因为滑雪的确很刺激.可是为了获得速度,滑的区域必须向下倾斜,而且当你滑到坡底,你不得不再次走上坡或者等待升降机来载你.Michael想知道载一个区域中最长底滑坡.区域由一个二维数组给出.数组的每个数字代表点的高度.下面是一个例子 1 2 3 4 5 16 17 18 19 6 15 24 25 20 7 14 23 22 21 8 13 12 11 10 9 一个人可以从某个点滑向上下左右相邻四个点之一,当且仅当高度减小.在上面的例子

2017.8.7 联考 期望的一个奇怪的题 书

Hazel有n本书,编号1为n到 ,叠成一堆.当她每次抽出一本书的时候,上方的书会因重力而下落,这本被取出的书则会被放置在书堆顶. 每次有pi的概率抽取编号为i的书.她每次抽书所消耗的体力与这本书在这堆中是第几本成正比.具体地,抽取堆顶的书所耗费体力值为1 ,抽取第二本耗费体力值为2 ,以此类推. 现在 想知道,在很久很久以后(可以认为几乎是无穷的),她每次抽书所耗费的体力的期望值是多少. 最终的答案显然可以表示成a/b的形式,请输出a*(b^-1)模1e9+7的值. [输入格式] 第一行一个整

《github一天一道算法题》:搜索二叉树接口实现大合集

读书.思考.写代码! 说明: (1)这里实现了搜索二叉树的全部常用操作 (2)限于时间和精力,实现的较为粗糙,内存泄露.成员变量访问控制.返回类型.异常安全等没有照顾的到 (3)一切实现的手段都是贴近底层操作,关注原理.以后可能对推倒重来,实现一个完备的接口系统. /********************************************* * [email protected] * 题目:二叉树接口实现大合集 * 具体:二叉树的创建.插入.最大值.最小值.前中后序递归遍历与非递

【NOIP模拟题】Graph(tarjan+dfs)

似乎我搞得太复杂了? 先tarjan缩点然后dfs就行了QAQ. (我不说我被一个sb错调了半个小时....不要以为缩点后dfs就可以肆无忌惮的不加特判判vis了.. bfs的做法:减反图,然后从大到小枚举(贪心),标记即可 #include <cstdio> #include <cstring> #include <cmath> #include <string> #include <iostream> #include <algorit