ZOJ 3795 Grouping 强连通分量-tarjan
2014-08-10 16:19
447 查看
一开始我还天真的一遍DFS求出最长链以为就可以了
不过发现存在有向环,即强连通分量SCC,有向环里的每个点都是可比的,都要分别给个集合才行,最后应该把这些强连通分量缩成一个点,最后保证图里是 有向无环图才行,这个时候再找最长链,当然缩点之后的scc是有权值的,不能只看成1,缩点完了之后,用记忆化搜索DP就可以再On的复杂度内求出结果
所以现学了一下SCC-Tarjan,所谓Scc-tarjan,就是找到强连通分量并且缩点,特别好用,其原理就是利用dfs时间戳,每个点有自己的时间戳,同时再开一个记录通过孩子的路径能指向的最上边的节点的时间戳,lowlink,如果当前lowlink就等于自己,即找到了强连通分量,并且找到了最大的头头。所以一个点也是强连通分量
不过发现存在有向环,即强连通分量SCC,有向环里的每个点都是可比的,都要分别给个集合才行,最后应该把这些强连通分量缩成一个点,最后保证图里是 有向无环图才行,这个时候再找最长链,当然缩点之后的scc是有权值的,不能只看成1,缩点完了之后,用记忆化搜索DP就可以再On的复杂度内求出结果
所以现学了一下SCC-Tarjan,所谓Scc-tarjan,就是找到强连通分量并且缩点,特别好用,其原理就是利用dfs时间戳,每个点有自己的时间戳,同时再开一个记录通过孩子的路径能指向的最上边的节点的时间戳,lowlink,如果当前lowlink就等于自己,即找到了强连通分量,并且找到了最大的头头。所以一个点也是强连通分量
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <vector> #include <stack> using namespace std; const int N = 100010; stack<int> sta; vector <int> G ; vector <int> G4 ; int vis ; int n,m; int pre ,lowlink ,sccno ,w ,dfs_clk,scc_cnt; int dp ; void init() { dfs_clk=scc_cnt=0; for (int i=0;i<=n;i++){ G[i].clear(); pre[i]=0; lowlink[i]=0; sccno[i]=0; vis[i]=0; w[i]=0; G4[i].clear(); } } void dfs(int u) { pre[u]=lowlink[u]=++dfs_clk; sta.push(u); for (int i=0;i<G[u].size();i++){ int v=G[u][i]; if (!pre[v]){ dfs(v); lowlink[u]=min(lowlink[u],lowlink[v]); } else if (!sccno[v]){ lowlink[u]=min(lowlink[u],pre[v]); } } if (lowlink[u]==pre[u]){ scc_cnt++; for (;;){ int x=sta.top();sta.pop(); sccno[x]=scc_cnt; w[scc_cnt]++; if (x==u) break; } } } void tarjan() { for (int i=1;i<=n;i++){ if (!pre[i]) dfs(i); } } void calc(int u) { if (dp[u]!=-1) return; dp[u]=w[u]; int now=w[u]; for (int j=0;j<G4[u].size();j++){ int v=G4[u][j]; calc(v); dp[u]=max(dp[u],dp[v]+now); } } void solve() { for (int i=1;i<=n;i++){ int u=sccno[i]; for (int j=0;j<G[i].size();j++){ int v=sccno[G[i][j]]; if (u!=v) G4[u].push_back(v); } } for (int i=1;i<=scc_cnt;i++){ dp[i]=-1; } for (int i=1;i<=scc_cnt;i++){ calc(i); } int ans=0; for (int i=1;i<=scc_cnt;i++){ ans=max(ans,dp[i]); } printf("%d\n",ans); } int main() { while (scanf("%d%d",&n,&m)!=EOF) { init(); int a,b; while (m--) { scanf("%d%d",&a,&b); G[a].push_back(b); } tarjan(); solve(); } return 0; }
相关文章推荐
- zoj 3795 Grouping tarjan缩点 + DGA上的最长路
- ZOJ 3795 Grouping(Tarjan缩点+DAG)
- zoj-3795-Grouping-tarjan确定最长的公路收缩
- ZOJ 3795 Grouping(Tarjan收缩点+DAG)
- ZOJ 3795 Grouping (tarjan缩点求最长链)
- zoj-3795-Grouping-tarjan缩点求最长路
- ZOJ_3795 Grouping(强连通分量 拓扑)
- zoj 3795 Grouping(强连通+dp)
- zoj 3795 Grouping(强连通缩点)
- ZOJ 3795 Grouping(强联通缩点,记忆化搜索)
- ZOJ 3795 Grouping 求最长链序列露点拓扑
- ZOJ 3795 Grouping(强联通分量 + 缩点 + Dp)
- ZOJ 3795 Grouping
- ZOJ 3795 Grouping 强联通缩点+拓扑序+偏序集的最大链的大小
- ZOJ 3795 Grouping 强连通缩点 + DAG最长路
- zoj 3795 Grouping 强连通缩点+拓扑排序最长链
- ZOJ-3795-Grouping 解题报告
- zoj 3795 Grouping(tarjin+dfs)
- ZOJ 3795 Grouping(强连通+最长路)
- 2014 Super Training #8 G Grouping --Tarjan求强连通分量