1. 程式人生 > >hihoCoder1183 tarjan演算法應用之割邊和割點

hihoCoder1183 tarjan演算法應用之割邊和割點

#include<cstdio>
#include<vector>
#include<algorithm>
using namespace std;
int n,m,order=0;
int low[20004],dfn[20004],father[20004],son[20004];
//father:父結點 son:子結點個數 
vector<int> cutpoint,edge[20004];
vector< pair<int,int> > cutedge;

void tarjan(int u)
{
	dfn[u]=low[u]=++order;
	bool flag=false;
	for (int i=0;i<edge[u].size();i++)
	{
		int v=edge[u][i];
		if(!dfn[v])
		{
			son[u]++;
			father[v]=u;
		 	tarjan(v);
			if(low[v]>=dfn[u]) flag=true;
			//點u為割點 
			if(low[v]>dfn[u]) cutedge.push_back(make_pair(min(v,u),max(v,u)));
			//邊v-u為割邊 
			low[u]=min(low[u],low[v]);
		}
		else if(v!=father[u]) low[u]=min(low[u],dfn[v]);
	}
	//根節點若有兩棵或兩棵以上的子樹則該為割點
	//非根節點若所有子樹節點均沒有指向u的祖先節點的回邊則為割點
	if((father[u]==0&&son[u]>1)||(father[u]&&flag)) cutpoint.push_back(u);
}

int main()
{
	scanf("%d%d",&n,&m);
	for (int i=1;i<=m;i++)
	{
		int u,v;
		scanf("%d%d",&u,&v);
		edge[u].push_back(v),edge[v].push_back(u);
	}
	tarjan(1);
	sort(cutedge.begin(),cutedge.end());
	sort(cutpoint.begin(),cutpoint.end());
	if(0==cutpoint.size()) puts("Null");
	else
	{
		printf("%d",cutpoint[0]);
		for (int i=1;i<cutpoint.size();i++) printf(" %d",cutpoint[i]);
		puts("");
	}
	for(int i=0;i<cutedge.size();i++) printf("%d %d\n",cutedge[i].first,cutedge[i].second);
}