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
- ZOJ 3795 Grouping 缩点拓扑序下求最长链
- ZOJ 3795 — Grouping 缩点+拓扑
- zoj 3795 Grouping 强连通缩点+拓扑排序最长链
- ZOJ 3795 Grouping 强联通缩点+拓扑序+偏序集的最大链的大小
- ZOJ 3795 Grouping (tarjan缩点求最长链)
- ZOJ 3795 Grouping 强连通缩点 + DAG最长路
- zoj-3795-Grouping-tarjan缩点求最长路
- ZOJ 3795 Grouping 强联通 最长路径
- ZOJ 3795 Grouping(Tarjan缩点+DAG)
- ZOJ 3795 Grouping(强联通分量 + 缩点 + Dp)
- zoj 3795 Grouping(强连通缩点)
- ZOJ 3795 Grouping(强连通+最长路)
- ZOJ 3795 Grouping(强联通缩点,记忆化搜索)
- ZOJ 3795 Grouping
- ZOJ 3795 Grouping
- ZOJ-3795 Grouping
- zoj 5303 Grouping 缩点求最长路
- ZOJ-3795-Grouping 解题报告
- [Network]Transport Layer
- 图的遍历算法-DFS
- 泛泰A870(高通600 cpu 720p) 刷4.4专用中文recovery TWRP2.7.1.1版(三版通刷)
- 我的大学,我的梦想
- WinCE 的发展史及相关基础知识
- ZOJ 3795 Grouping 缩点拓扑序下求最长链
- poj3311 经典tsp问题
- 【数据结构】给出一个链表,遍历一次就找到中间节点
- leetcode: Interleaving String
- 铁路栈问题
- 算法题 1 判断两条单链表是否交叉 一百度实习笔试题(2012.5.6)
- 九度 题目1052:找x
- DataGridView控件绑定数据源
- Name Count -- Javascript 实现