程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> ZOJ 3795 Grouping 縮點拓撲序下求最長鏈

ZOJ 3795 Grouping 縮點拓撲序下求最長鏈

編輯:C++入門知識

題意:給定n個點,m條有向邊。

把點分成幾個集合使得每個集合中的任意2點都不可達(一個集合只存放一個點也可以)

問最少需要分成幾個集合。

如果沒有環,則這個題目就是求有向圖的最長鏈,拓撲序下跑bfs即可。

但是有環,所以把環縮點成新點x,而點x的點權就是x點在原圖中對應的頂點個數。

縮點後就是有向無環圖,繼續跑一個拓撲序。


#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
using namespace std;
#define N 100010
//N為最大點數
#define M 301000
//M為最大邊數
int n, m;//n m 為點數和邊數

struct Edge{
	int from, to, nex;
	bool sign;//是否為橋
}edge[M<<1];
int head[N], edgenum;
void add(int u, int v){//邊的起點和終點
	Edge E={u, v, head[u], false};
	edge[edgenum] = E;
	head[u] = edgenum++;
}

int DFN[N], Low[N], Stack[N], top, Time; //Low[u]是點集{u點及以u點為根的子樹} 中(所有反向弧)能指向的(離根最近的祖先v) 的DFN[v]值(即v點時間戳)
int taj;//連通分支標號,從1開始
int Belong[N];//Belong[i] 表示i點屬於的連通分支
bool Instack[N];
vector bcc[N]; //標號從1開始

void tarjan(int u ,int fa){  
	DFN[u] = Low[u] = ++ Time ;  
	Stack[top ++ ] = u ;  
	Instack[u] = 1 ;  

	for (int i = head[u] ; ~i ; i = edge[i].nex ){  
		int v = edge[i].to ;  
		if(DFN[v] == -1)
		{  
			tarjan(v , u) ;  
			Low[u] = min(Low[u] ,Low[v]) ;
			if(DFN[u] < Low[v])
			{
				edge[i].sign = 1;//為割橋
			}
		}  
		else if(Instack[v]) Low[u] = min(Low[u] ,DFN[v]) ; 		
	}  
	if(Low[u] == DFN[u]){  
		int now;
		taj ++ ; bcc[taj].clear();
		do{
			now = Stack[-- top] ;  
			Instack[now] = 0 ; 
			Belong [now] = taj ;
			bcc[taj].push_back(now);
		}while(now != u) ;
	}
}

void tarjan_init(int all){
	memset(DFN, -1, sizeof(DFN));
	memset(Instack, 0, sizeof(Instack));
	top = Time = taj = 0;
	for(int i=1;i<=all;i++)if(DFN[i]==-1 )tarjan(i, i); //注意開始點標!!!
}
vectorG[N];
int du[N];

void suodian(){
	for(int i = 1; i <= taj; i++)G[i].clear(), du[i] = 0;
	for(int i = 0; i < edgenum; i++){
		int u = Belong[edge[i].from], v = Belong[edge[i].to];
		if(u!=v)G[u].push_back(v), du[v]++;
	}
}
void init(){memset(head, -1, sizeof(head)); edgenum=0;}
int dis[N];
int bfs(){
	queueq;
	for(int i = 1; i <= taj; i++)
		if(du[i]==0){q.push(i); dis[i] = bcc[i].size();}
		else dis[i] = 0;
	while(!q.empty()){
		int u = q.front(); q.pop();
		for(int i = 0; i < G[u].size(); i++){
			int v = G[u][i];
			dis[v] = max(dis[u]+(int)bcc[v].size(), dis[v]);
			du[v]--;
			if(du[v]==0)
			q.push(v);
		}
	}
	int ans = 1;
	for(int i = 1; i <= taj; i++)ans = max(ans, dis[i]);
	return ans;
}
int main()
{
	int i,j,u,v;
	while(~scanf("%d %d",&n,&m)){
		init();
		while(m--){
			scanf("%d %d",&u,&v); if(u!=v)
			add(u,v);
		}
		tarjan_init(n);
		suodian();
		printf("%d\n",bfs());
	}
	return 0;
}
/*
5 5 
1 2
2 3
3 4
4 1
5 1

4 4
1 2
2 3
3 4
4 1

5 3
1 2
2 3
3 4




*/


  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved