我最近學會了線性時間算法來計算圖形中的鉸接點。我的實現在Online Judge測試數據上正確運行,所以代碼沒有問題。然而,我似乎很難在DFS運行中發現多於一個的相同關節點。讓我解釋一下在Taljan的實現中重複出現的鉸接點
我有一個列表,如果遇到關節點存儲。現在,當我最終打印列表時,我會得到正確的關節點,但是關節點的幾個頂點會出現多次。據我所知,這不應該發生,因爲我們只遇到每個頂點一次。那麼爲什麼我會重複列表中的條目?爲了解決這個問題,我在我的原始代碼中使用了一個HashSet來存儲它們,並在最後輸出正確答案的內容。這是我的問題代碼。該算法主要是基於關閉維基百科上的僞代碼這裏:https://en.wikipedia.org/wiki/Biconnected_component
這裏是我在C implmentation ++代碼:
/*input
7 6
0 1
1 2
3 4
2 4
2 6
5 2
*/
#include <bits/stdc++.h>
using namespace std;
#define endl '\n'
#define pb emplace_back
#define sz 3005 //In the current scenario, I need only a maximum on 3000 vertices
typedef long long int ll;
//Created by Shreyans Sheth [bholagabbar]
bool visited [sz]; //whether the node has been discoverd in the DFS run or not
int low [sz]; //time of the earliest discovered vertex reachable from the vertex
int disc [sz]; //time at which vertex was explored
int parent [sz]; //stores the parents of each vertex
vector<int> a[sz]; //Adjacency List for graph
int rtime; //Time
vector<int> ap; //Stored the articulation points
void DFS(int s)
{
visited[s]=1;
low[s]=disc[s]=++rtime;
int nchild=0;
for(auto i:a[s])
{
if(!visited[i])
{
nchild++;//INcrement children of the current vertex
parent[i]=s;
DFS(i);
low[s]=min(low[s],low[i]);
/* s is an articulation point iff
1. It the the root and has more than 1 child.
2. It is not the root and no vertex in the subtree rooted at one of its
children has a back-link to its ancestor.
A child has a back-link to an ancestor of its parent when its low
value is less than the discovery time of its parent.*/
if((parent[s]==-1 && nchild>1)||(parent[s]!=-1 && low[i]>=disc[s]))
ap.pb(s);//Adding the articulation points. How are they repeated?
}
else if(visited[i] && i!=parent[s])
low[s]=min(low[s],disc[i]);
}
}
void ArticulationPoints(int n)//Driver Funtion
{
ap.clear();
rtime=0;//The time for each cycle of DFS
for(int i=0;i<n;i++)
{
parent[i]=-1;//Initializing parents as -1. True for roots
visited[i]=0;//All points not visited
low[i]=disc[i]=INT_MAX;
}
for(int i=0;i<n;i++)
if(!visited[i])//Vertex not discoverdd
DFS(i);
}
int main()
{
int n,m;//number of vertices, edges
cin>>n>>m;
for(int i=0;i<m;i++)//Building Graph
{
int x,y;
cin>>x>>y;
a[x].pb(y);
a[y].pb(x);
}
ArticulationPoints(n);//Calculating Articulation points
cout<<"Articulation Points are:\n";
for(int i:ap)
cout<<i<<endl;
return 0;
}
代碼輸入和輸出:http://ideone.com/u5dYOy(見2是怎麼來三次?)
爲什麼會發生這種情況?我在算法中遺漏了什麼?我相信我對算法的運行有一個公平的想法。任何幫助表示讚賞。由於
謝謝!我查了一下,然後if語句修正了它。此外,bits/stdC++在節目競賽中節省了大量時間。我知道在軟件開發中這是不好的做法 – bholagabbar
關於僞代碼部分,我參考了一個實際的實現[這裏](https://github.com/kartikkukreja/blog-codes/blob/master/src/Articulation% 20Points%20or%20Cut%20Vertices%20with%20DFS.cpp)。這增加了每個節點的時間。所以我也這樣做了。我不會太重要嗎?另外,如果我每次都遵循僞代碼並傳遞'd'參數,那麼'ArticulationPoint'函數中每個成功'if'條件都會傳遞'd'的值? – bholagabbar
@bholagabbar你是對的,它看起來像這個算法,'d'可以是發現時間(你在做什麼)或深度(我建議)。這裏沒關係。如果你使用'd'參數,每次從'ArticulationPoint'調用'DFS',其中'C'是常量(通常爲0或1)。 – IVlad