Tarjan缩点

缩点含义:将一个环缩成一个点,然后把原本环上的点与外界相连的边,接到这个点上面。
                  就是 tarjan求出的所有强连通分量都变成点,这样有向有环图就变成有向无环图(DAG)。

缩点做法:stack栈回溯的时候,环中点的权值都加到最先遍历的点上。

                   根据回溯时染成的颜色构建新的树。

额外知识:将有向有环图变做强连通图

                  只需要变作无环图,计算每个连通分量的入度和出度

                  计算入度为零的点数为a,出度为零的点数为b

                  那么我们至少需要添加的边数为max(a,b)。


[代码]

#include
#include
#include
#include 
using namespace std;

struct ss{
	int v;
	int next;
	int u;
}s1[5000],s2[5000]; 

int head[1000];//边序 
int dfn[1000];
int low[1000];
int a[1000];//每个点的权值 
int vis[1000];//判断在不在栈中 
int color[1000];//染色 
int n,m;
int cnt;
int num;
stackst;

void init()
{
	memset(head,-1,sizeof(head));
	memset(vis,0,sizeof(vis));
	memset(dfn,0,sizeof(dfn));
	memset(low,0,sizeof(low));
	memset(a,0,sizeof(a));	
	num=0;
	cnt=0;
}
void add(int u,int v,ss* s)
{
	s[num].u = u;
	s[num].v = v;
	s[num].next = head[u];
	head[u] = num++;
}
void Tarjan(int u)
{
	st.push(u);
	dfn[u] = low[u] = ++cnt;
	vis[u]=1;

	for(int i = head[u]; i != -1; i = s1[i].next)
	{
		int v = s1[i].v;
		if(!dfn[v])//不曾访问过 
		{
			Tarjan(v); 
			low[u] = min(low[u],low[v]);
		}
		else if(vis[v])
			low[u] = min(low[u],dfn[v]);
	}	
	
	if(dfn[u]==low[u])
	{	
		int now; 
		do{	//取出包括u的环->缩点 
			now=st.top();
			color[now]=u; //染色 
			vis[now]=0;
			st.pop();
			a[u]+=a[now];//合并权值->u 
		}while(now!=u);
		a[u]/=2;//最后出栈的时候多加了a[u] 
	}
	return;	
} 
int main()
{
	while(~scanf("%d%d",&n,&m) && (m+n))
	{
		memset(head,-1,sizeof(head));
		memset(vis,0,sizeof(vis));
		int u,v;
		for(int i=1;i<=m;i++)
		{
			scanf("%d%d",&u,&v);
			add(u,v,s1);
		}
		for(int i=1;i<=n;i++)
			scanf("%d",&a[i]);
		for(int i=1;i<=n;i++)
			if(!dfn[i])
				Tarjan(i);
		//缩点之后,再重新建一遍新图 s2
	        //如果颜色不同,建立新边连接缩点
		//讲真为了方便,将u点也存进结构体
		num= 0;//边数初始化 
		for(int i=1;i<=m;i++)//构建新树
	        if(color[s1[i].u]!=color[s1[i].v])//剩余的点无环只会连接一次 
	        	add(color[s1[i].u],color[s1[i].v],s2); 
		for(int i=0;i%d\n",s2[i].u,s2[i].v); 
			printf("%d==%d\n",s2[i].u,a[s2[i].u]); 
			printf("%d==%d\n\n",s2[i].v,a[s2[i].v]); 
		}		
	} 
	return 0; 
} 

 

你可能感兴趣的:(Tarjan,Tarjan缩点)