ZOJ 3795 Grouping 求最长链序列露点拓扑

意甲冠军:特定n积分。m向边条。

该点被划分成多个集合随机的每个集合,使得2问题的关键是无法访问(集合只能容纳一个点)

问至少需要被分成几个集合。

假设没有戒指,接着这个话题正在寻求产业链最长的一个有向图。拓扑序运行bfs您可以。

但是有一个环,所以把环缩点成新点x。而点x的点权就是x点在原图中相应的顶点个数。

缩点后就是有向无环图,继续跑一个拓扑序。


#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <set>
#include <map>
#include <string>
#include <math.h>
#include <stdlib.h>
#include <time.h>
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<int> 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); //注意開始点标!。!

} vector<int>G[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(){ queue<int>q; 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 */



posted @ 2015-12-15 13:36  mfrbuaa  阅读(212)  评论(0编辑  收藏  举报