hdu--1269--tarjan<有疑惑>

这2天 每天学个新的算法吧...可以的话....

tarjan的代码 还是很容易写的 也很容易构图 但总觉得有些细节不那么好理解

传送1

传送2

怎么说呢 总觉得他定义的 low数组含义是有问题的

这是 原作者下的定义

定义DFN(u)为节点u搜索的次序编号(时间戳),Low(u)为u或u的子树能够追溯到的最早的栈中节点的次序号

DFN数组的定义 我觉得没问题...但是 Low[u]数组的定义与我代码检验出来的结果并不相同... 当low[x] low[y] low[z]...low[n]是相等的时候 我们说x y z …………n是在一个连通分量之中的  但是显然我们经过模拟 可以得到如下答案 -- 就是根据那张经典图

6 8
1 2
2 4
4 6
5 6
3 4
3 5
4 1
1 3
标号 i  No[i]  father[i]
  1       1        1
  2       6        5
  3       2        1
  4       5        1
  5       3        3
  6       4        4

所以 我想low数组的定义不太恰当..

然后 另外一篇博客上是这样介绍的

这样,我们用low值记录该点所在强连通子图对应的搜索子树的根节点的Dfn值。注意,该子树中的元素在栈中一定是相邻的,且根节点在栈中一定位于所有子树元素的最下方

注意下 这边指的最下方 是指在栈这个数据结构之中..因为根结点首先被push进去 然后stack元素入栈是压上面的 所以根结点就在最下面了

如果遍历完整个搜索树后某个点的dfn值等于low值,则它是该搜索子树的根。这时,它以上(包括它自己)一直到栈顶的所有元素组成一个强连通分量‘

这句话 是毫无疑问正确 这也是很重要的一点

强连通分量是由若干个环组成的。所以,当有环形成时(也就是搜索的下一个点已在栈中),我们将这一条路径的low值统一,即这条路径上的点属于同一个强连通分量。

这边 他的说法 又和我的结果有点矛盾...虽然在同一个连通块之中 但是low[]值并没有统一

***********************

还有 这题我做的时候 当我修改了下    father[u] = min( father[u] , No[v] );   ----------->father[u] = min( No[u] , No[v] );

任然是AC的 而且我测了几组的话 输出的dfn low数组也是相同的.....

我就更奇怪了 -.-

要是 我有些想法了 再随时来更新 写下来... 顺便 明天去和porker大神请教下..

  1 //横插边:连接到已经出栈的节点的边;
  2 //后向边:连接到已在栈中节点的边;
  3 //树枝边: 在搜索树中的边。
  4 #include <iostream>
  5 #include <cstring>
  6 #include <stack>
  7 #include <algorithm>
  8 using namespace std;
  9
 10 int cnt , n , sum , index;
 11 const int size = 10010;
 12 int No[size];
 13 int father[size];
 14 bool vis[size];
 15 struct graph
 16 {
 17     int to;
 18     int next;
 19 }edge[size*10];
 20 int head[size];
 21 stack<int>s;
 22
 23 void init( )
 24 {
 25     memset( head , -1 , sizeof(head) );
 26     memset( vis , false , sizeof(vis) );
 27     memset( No , 0 , sizeof(No) );
 28 }
 29
 30 void add( int st , int end )
 31 {
 32     while( !s.empty() )
 33         s.pop();
 34     edge[cnt].to = end;
 35     edge[cnt].next = head[st];
 36     head[st] = cnt++;
 37 }
 38
 39 void tarjan( int u )
 40 {
 41     int temp , v;
 42     No[u] = father[u] = index++;
 43     vis[u] = true;
 44     s.push(u);
 45     for( int i = head[u] ; ~i ; i = edge[i].next )
 46     {
 47         v = edge[i].to;
 48         if( !No[v] )
 49         {
 50             tarjan(v);
 51             father[u] = min( father[u] , father[v] );
 52         }
 53         else if( vis[v] )
 54         {
 55             father[u] = min( father[u] , No[v] );
 56         }
 57     }
 58     if( No[u] == father[u] )
 59     {
 60         sum ++;
 61         while(1)
 62         {
 63             temp = s.top();
 64             s.pop();
 65             vis[temp] = false;
 66             if( No[temp]==father[temp] )
 67                 break;
 68         }
 69     }
 70 }
 71
 72 int main()
 73 {
 74     cin.sync_with_stdio(false);
 75     int m , x , y;
 76     while( cin >> n >> m &&(n||m) )
 77     {
 78         init();
 79          sum = cnt = 0;
 80          index = 1;
 81         while( m-- )
 82         {
 83             cin >> x >> y;
 84             add(x,y);
 85         }
 86         for( int i = 1 ; i<=n ; i++ )
 87         {
 88             if( !No[i] )
 89             {
 90                 tarjan(i);
 91             }
 92         }
 93         //for( int i = 1 ; i<= n ;i++ )
 94         //{
 95         //    cout << i << " " << No[i] << "  " << father[i] << endl;
 96         //}
 97         if( sum==1 )
 98             cout << "Yes" << endl;
 99         else
100             cout << "No" << endl;
101     }
102     return 0;
103 }
104 /*
105 6 8
106 1 2
107 2 4
108 4 6
109 5 6
110 3 4
111 3 5
112 4 1
113 1 3
114 标号 i  No[i]  father[i]
115   1       1        1
116   2       6        5
117   3       2        1
118   4       5        1
119   5       3        3
120   6       4        4
121  */

刚刚翻了下白书上是这样定义的:

low[u]为u及其后代能追溯到的最早<最先被发现>祖先点v的dnf[v]值

today:

  回来 本身就是充满悲情色彩的一个词

  因为  无论最终他有没有回来

  但是  他曾经离开过你

  

时间: 2024-10-13 00:28:19

hdu--1269--tarjan<有疑惑>的相关文章

hdu 1269(tarjan)

就是板子,这次没看板子,自己写的 #include <iostream> #include <cstdio> #include <cstring> #include <cstdio> #include <algorithm> #include <vector> #include <queue> #include <cmath> #include <stack> #include <set>

hdu 1269 tarjan求强连通分量

tarjan求强连通分量的裸题复习,直接上代码: 1 #include <stack> 2 #include <cstdio> 3 #include <cstring> 4 using namespace std; 5 6 const int N = 10001; 7 const int M = 100000; 8 int dfn[N], low[N], head[N]; 9 bool inStack[N]; 10 int n, m, e, cnt, dfs_clock

hdu 1269 迷宫城堡 (tarjan算法学习)

迷宫城堡 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 7056    Accepted Submission(s): 3137 Problem Description 为了训练小希的方向感,Gardon建立了一座大城堡,里面有N个房间(N<=10000)和M条通道(M<=100000),每个通道都是单向的,就是说若称某通道连通了A

HDU 1269 强连通分量tarjan算法

迷宫城堡 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 6655    Accepted Submission(s): 2973 Problem Description 为了训练小希的方向感,Gardon建立了一座大城堡,里面有N个房间(N<=10000)和M条通道(M<=100000),每个通道都是单向的,就是说若称某通道连通了A房

强连通分量分解 tarjan算法 (hdu 1269)

题意: 给出一个有n个点m条边的有向图,判断该图是否只有一个强连通分量. 限制: 0 <= N <= 10000 0 <= M <= 100000 思路: tarjan算法分解强连通分量. /*强连通分量分解 tarjan算法 (hdu 1269) 题意: 给出一个有n个点m条边的有向图,判断该图是否只有一个强连通分量. 限制: 0 <= N <= 10000 0 <= M <= 100000 */ #include<iostream> #inc

hdu 1269 迷宫城堡

迷宫城堡 Time Limit : 2000/1000ms (Java/Other)   Memory Limit : 65536/32768K (Java/Other) Total Submission(s) : 29   Accepted Submission(s) : 12 Font: Times New Roman | Verdana | Georgia Font Size: ← → Problem Description 为了训练小希的方向感,Gardon建立了一座大城堡,里面有N个房

[HDU] 迷宫城堡 HDU - 1269

迷宫城堡 HDU - 1269 时限: 1000MS   内存: 32768KB   64位IO格式: %I64d & %I64u 问题描述 为了训练小希的方向感,Gardon建立了一座大城堡,里面有N个房间(N<=10000)和M条通道(M<=100000),每个通道都是单向的,就是说若称某通道连通了A房间和B房间,只说明可以通过这个通道由A房间到达B房间,但并不说明通过它可以由B房间到达A房间.Gardon需要请你写个程序确认一下是否任意两个房间都是相互连通的,即:对于任意的i和j

【HDU 1269】迷宫城堡

[HDU 1269]迷宫城堡 强联通模板 要求全图只有一个强联通分量 成立则Yes否则No 可能有一些独立的点 所以要从头到尾遍历 为此献了几个WA 节哀 代码如下 #include <cstdio> #include <cstdlib> #include <cstring> #include <vector> #include <stack> using namespace std; vector <int> head[11111]

HDU 1269 迷宫城堡(强连通)

HDU 1269 迷宫城堡 题目链接 题意:中文题 思路:强连通模板题 代码: #include <cstdio> #include <cstring> #include <vector> #include <stack> using namespace std; const int N = 10005; int n, m; vector<int> g[N], scc[N]; int pre[N], lowlink[N], sccno[N], d

Hdu 1269 强连通判定

题目链接 迷宫城堡 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 7097    Accepted Submission(s): 3159 Problem Description 为了训练小希的方向感,Gardon建立了一座大城堡,里面有N个房间(N<=10000)和M条通道(M<=100000),每个通道都是单向的,就是说若称某通道