强联通分量targin模板(poj2186)

http://poj.org/problem?id=2186

//poj2186 强联通图模板 节点数1W 边数5W  79ms  G++  
#include
const int sz = 50000+10; 
struct Edge
{
	int to;
	int next;
};
Edge edge[sz]; //存放边 
int head[sz]={0};//每个节点的第一条边的编号 
int n,m;//有n个节点,m条边 
int cnt;//边的编号 

int stack[sz];//栈 
int top;
int dfn[sz]={0},low[sz]={0};//targin要用的变量 
bool instack[sz]={false};//是否存在栈中 
int c = 0;//递增量 ,时间戳 
int sc = 0 ;//一共有多少个联通分量
int count[sz]={0};//每个联通分量有多少个节点 
int min(int a,int b)
{
	return a1){
				printf("0\n");
				return ;
			}
			id = i;
		}
	}
	printf("%d\n",count[id]);
}
void init()
{
	sc = cnt = top = 0;
	for(int i=1;i<=n;i++)
	{
		dfn[i]=low[i]=head[i]=count[i]=0;
		instack[i]=false;
	}
}
int main()
{
	scanf("%d %d",&n,&m);
	init();
	for(int i=1;i<=m;i++)
	{
		int u,v;
		scanf("%d %d",&u,&v);
		addEdge(u,v);
	}
	
	for(int i=1;i<=n;i++)//不联通 
	{
		if(dfn[i]==0)
		{
			targin(i);
		}
	}
	solve();
	return 0;
}

    强联通图缩点后:得到一个DAG(有向无环图),得到这个DAG我们可以处理一些问题:
    1.问:是否存在某些点(point1或point2 。。。。。),使得 所有的点是否可以汇聚到这个点(point1 或 point2 。。。。。)上,比如3个点1 2 3 ,1-->2  2-->1  2-->3 画图可知 1 2 都可以汇聚到3上面,
      问题可以转化为 一共有多少个出度为0 的强连通图 ,如果只有1个,则结果就是该连通图的节点数,如果>1 ,则没有。因为最终的DAG,如果有2个强联通图没有出度,
      则必定有一个点 得不到另外一个点的汇聚。
    2.问:有一个消息,如果A 到B右一条有向边A-->B,则A可以把消息传给B,问我们至少需要选择多少个点,作为信息的源点,最终可以使得每一个节点都获得该 消息
      问题转化为: 一共有多少个节点没有入度,因为没有入度的点没有消息来源,我们需要选择它作为源点
    3.问: 我们至少需要添加多少条有向边,才可以使得整个图为强联通图
      问题转化为: 计算得到 入度为0的强联通图个数 in0 , 计算得到出度为0的强联通图的个数 out0,然后结果就是max(in0,out0)。因为强联通图必然是每个点都有出度和入度,
      所以我们必须为没有入度或者出度的点 连边,那么最少就需要max(in0,out0)条边。
       

你可能感兴趣的:(算法_图)