强连通分量(缩点+求出入为0的点的个数)HDU 2767 Proving Equivalences
2018-01-22 16:18
579 查看
用了半天的时间将强连通分量中的trajan算法及其代码实现这部分终于理解通透了。下面是我针对一道例题对其进行的阐释。
题目大意:
经过自己的理解,将代码进行的分析。
感受:
运用了缩点,学会了找出入度为0的点的求法
题目大意:
给你一个有向图,问你在图中最少要加多少条边能使得该图变成一个强连通图.题目思路:
首先我们求出该图的各个强连通分量,然后把每个强连通分量看出一个点(即缩点),然后我们得到了一个有向无环图(DAG). 对于一个DAG,我们需要添加max(a,b)条边才能使其强连通.其中a为DAG中出度为0的点总数,b为DAG中入度为0的点总数. 注意特殊情况:如果图已经强连通了,我们需要添加的边是0条,而不是1条.这道题是参照http://blog.csdn.net/u013480600/article/details/31805017
经过自己的理解,将代码进行的分析。
感受:
运用了缩点,学会了找出入度为0的点的求法
#include<iostream> #include<stdio.h> #include<vector> #include<stack> #include<string.h> #include<algorithm> const int maxn=20000+10; using namespace std; vector<int>G[maxn]; stack<int>S; int dfs_clock; int scc_cnt;//强连通分量的个数 int n,m; int pre[maxn]; int low[maxn]; int sccno[maxn]; bool in0[maxn],out0[maxn]; void dfs(int u) { pre[u]=low[u]=++dfs_clock; S.push(u);//每搜一个就将其存入stack for(int i=0;i<G[u].size();i++) { int v=G[u][i]; if(!pre[v])//当pre为0的时候,就是还没有初始化,可见还没有搜到这个点。代替了visit { dfs(v); low[u]=min(low[u],low[v]); } else if(!sccno[v])//说明v还在G图里.值为0说明还未被踢 { low[u]=min(low[u],low[v]);//这里有的人也写成low[u]=min(low[u],pre[v]),实际上结果都一样,只不过pre的值始终不变。而low的值一直在更新 } } if(low[u]==pre[u])//说明u点是强分量起点 { scc_cnt++; while(true) { int x=S.top(); S.pop(); sccno[x]=scc_cnt;//在这个地方进行了缩点操作,sccno数组记录的就是缩点后的值 if(x==u) break; } } } void find_scc(int n)//此处将预处理和找scc强连通图进行了结合 { scc_cnt=dfs_clock=0; memset(pre,0,sizeof(pre)); memset(sccno,0,sizeof(sccno)); for(int i=0;i<n;i++) { if(!pre[i]) dfs(i); } } int main() { int T;scanf("%d",&T); while(T--) { scanf("%d%d",&n,&m); for(int i=0;i<n;i++) { G[i].clear(); } while(m--) { int u,v; scanf("%d%d",&u,&v); u--,v--; G[u].push_back(v); } find_scc(n); for(int i=1;i<=scc_cnt;i++) { in0[i]=out0[i]=true; } for(int u=0;u<n;u++) { for(int i=0;i<G[u].size();i++) { int v=G[u][i]; if(sccno[u]!=sccno[v]) { out0[sccno[u]]=in0[sccno[v]]=false;//由于u->v,u的入度为0,出度不为0;而v反之。所以这个出入对应要消掉。in0[]为true表示入度为0,out[]为true表示出度为0 } } } int a=0;int b=0; for(int i=1;i<=scc_cnt;i++) { if(in0[i]) a++; if(out0[i]) b++; } int ans=max(a,b); if(scc_cnt==1)//这一步一定要有。因为此图是一个强连通,则添加的为0 ans=0; printf("%d\n",ans); } return 0; }
相关文章推荐
- HDU 2242 连通分量缩点+树形dp
- Hdu 2767 把森林变成强连通分量.cpp
- [HDU 2767]Proving Equivalences[Tarjan强连通缩点缩点]
- -----tarjan强连通分量缩点-hdu 5934 -Bomb
- hdu 2767 Proving Equivalences(强连通 缩点 以及判断入度 出度)
- HDU 2767 强连通之缩点
- HDU 4612 Warm up(无向图强连通分量缩点建树)
- HDU 2767 Proving Equivalences(强连通 Tarjan+缩点)
- hdu 2767 Proving Equivalences 强连通 缩点 求度
- hdu 3836 Equivalent Sets hdu 2767 Proving Equivalences 强连通缩点入门
- HDU 4587 TWO NODES 删除两个点求连通分量
- HDU4971 A simple brute force problem.(强连通分量缩点 + 最大权闭合子图)
- UVA 11324 有向图强连通分量缩点得SCC图,并在其上求最长路径
- hdu 1269 tarjan求强连通分量
- hdu 1269 Tarjan强连通分量 模板
- hdu 3639 Hawk-and-Chicken (强连通 + 反图 + 缩点) && hdu1827 Summer Holiday && hdu 1269 迷宫城堡 && hdu3072 Intelligence System
- 图论复习之强连通分量以及缩点—Tarjan算法
- HDU-4635 Strongly connected 强连通,缩点
- Network of Schools POJ - 1236 tarjan强连通分量缩点
- HDU_1269_tarjan求强连通分量