ZOJ 3795 Grouping 缩点拓扑序下求最长链

来源:互联网 发布:学好java的心得 编辑:程序博客网 时间:2024/05/18 20:32

题意:给定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 22 33 44 15 14 41 22 33 44 15 31 22 33 4*/


0 0
原创粉丝点击