HDU3836 强联通 裸题


#include<cstdio>
#include<stdlib.h>
#include<string.h>
#include<string>
#include<map>
#include<cmath>
#include<iostream>
#include <queue>
//#include <stack>
#include<algorithm>
#include<set>
using namespace std;
#define INF 1e8
#define eps 1e-8
#define LL __int64
#define maxn 26
#define mol 1000000007
#define N 20010
#define M 50010
struct Edge  
{  
	int v;  
	int next;  
};  
Edge edge[M];//边的集合  

int node[N];//顶点集合  
int instack[N];//标记是否在stack中  
int stack[N];  
int Belong[N];//各顶点属于哪个强连通分量  
int DFN[N];//节点u搜索的序号(时间戳)  
int LOW[N];//u或u的子树能够追溯到的最早的栈中节点的序号(时间戳)  
int n, m;//n:点的个数;m:边的条数  
int cnt_edge;//边的计数器  
int Index;//序号(时间戳)  
int top;  
int Bcnt;//有多少个强连通分量  
int in[N],out[N],numd[N],c[N];
void add_edge(int u, int v)//邻接表存储  
{  
	edge[cnt_edge].next = node[u];  
	edge[cnt_edge].v = v;  
	node[u] = cnt_edge++;  
}  
void tarjan(int u)  
{  
	int i, j;  
	int v;  
	DFN[u] = LOW[u] = ++Index;  
	instack[u] = true;  
	stack[++top] = u;  
	for (i = node[u]; i != -1; i = edge[i].next)  
	{  
		v = edge[i].v;  
		if (!DFN[v])//如果点v没被访问//树枝边  
		{  
			tarjan(v);  
			if (LOW[v]<LOW[u])  
				LOW[u] = LOW[v];  
		}  
		else//如果点v已经被访问过//后向边  
			if (instack[v] && DFN[v]<LOW[u])  
				LOW[u] = DFN[v];  
	}  
	if (DFN[u] == LOW[u])//缩点  
	{  
		Bcnt++;  
		do  
		{  
			j = stack[top--];  
			instack[j] = false;  
			Belong[j] = Bcnt;  
		} while (j != u);  
	}  
}  
void solve()  
{  
	int i;  
	top = Bcnt = Index = 0;  
	memset(DFN, 0, sizeof(DFN));  
	memset(LOW, 0, sizeof(LOW));  
	memset(Belong, 0, sizeof(Belong)); 
	for (i = 1; i <= n; i++)  
		if (!DFN[i])  
			tarjan(i);  
}  
int main()  
{  
	//freopen("in.txt", "r", stdin);  
	int i, j, k, t;  
	while(~scanf("%d%d",&n,&m))
	{
		cnt_edge = 0;  
		memset(node, -1, sizeof(node));  

		for (i = 1; i <= m; i++)  
		{  
			scanf("%d%d", &j,&k);
				add_edge(j,k);  
		}  
		solve();  
		memset(in,0,sizeof(in));
		memset(out,0,sizeof(out));
		//memset(numd,127,sizeof(numd));
		if(Bcnt==1)
		{
		   printf("0\n");
		   continue;
		}
		for(i=1;i<=n;i++)
		{
			for(j=node[i];j!=-1;j=edge[j].next )
			{
				if(Belong[i]!=Belong[edge[j].v])
				{
					in[Belong[edge[j].v]]++;
					out[Belong[i]]++;
				}
			}
		}
		int a=0,b=0;
		for(j=1;j<=Bcnt;j++)
		{
			if(!in[j]) 
				a++;
	        if(!out[j])
				b++;
			
		}
		printf("%d\n",max(a,b));
	}
	return 0;  
}


你可能感兴趣的:(HDU3836 强联通 裸题)