HDU-2767-tarjan/Kosaraju求scc
http://acm.hdu.edu.cn/showproblem.php?pid=2767
问最少添加几条边使得图为强连通。
tarjan跑一下,然后对强连通分量缩点,找下此时出度为零和入度为零的点数输出较大者即可。
tarjan,dfn数组也同时起到了标记的作用,如果未标记说明此时的边就是dfs树上的边,否则的话,如果v已经处于某个scc中说明这条边是交叉边,不用考虑(因为一定无对应的回边,有的话这个点就应该和v属于同一个scc,与过程矛盾)。否则就是回边了,和求桥和割点的方法类似求dfn以及low数组。
最后如果low[u]==dfn[u]说明u沿着他的孩子能回到他自己,这就形成了一个环,环上的所有点构成了一个scc,不断出栈直到u出现为止统计下scc。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<map>
#include<set>
#include<stack>
#include<deque>
#include<bitset>
#include<unordered_map>
#include<unordered_set>
#include<queue>
#include<cstdlib>
#include<ctype.h>
#include<ctime>
#include<functional>
#include<algorithm>
#include<bits/stdc++.h>
using namespace std;
#define LL long long
#define pii pair<int,int>
#define mp make_pair
#define pb push_back
#define fi first
#define se second
#define inf 0x3f3f3f3f
#define debug puts("debug")
#define mid ((L+R)>>1)
#define lc (id<<1)
#define rc (id<<1|1)
const int maxn=;
const int maxm=;
const double PI=acos(-1.0);
const double eps=1e-;
const LL mod=1e9+;
LL gcd(LL a,LL b){return b==?a:gcd(b,a%b);}
LL lcm(LL a,LL b){return a/gcd(a,b)*b;}
LL qpow(LL a,LL b,LL c){LL r=; for(;b;b>>=,a=a*a%c)if(b&)r=r*a%c;return r;}
template<class T>
void prt(T v){for(auto x:v)cout<<x<<' ';cout<<endl;}
struct Edge{int u,v,w,next;}; int dfn[maxn],low[maxn],scc[maxn],scc_cnt,sum;
int in[maxn],out[maxn];
vector<int>g[maxn];
stack<int>S;
void dfs(int u){
dfn[u]=low[u]=++sum;
S.push(u);
for(int v:g[u]){
if(!dfn[v]){
dfs(v);
low[u]=min(low[u],low[v]);
}else if(!scc[v]){
low[u]=min(low[u],dfn[v]);
}
}
if(dfn[u]==low[u]){
++scc_cnt;
int x=-;
for(;;){
x=S.top();S.pop();
scc[x]=scc_cnt;
if(x==u)break;
}
}
}
int main(){
int t,n,m,i,j,k,u,v;
scanf("%d",&t);
while(t--){
scanf("%d%d",&n,&m);
for(i=;i<=n;++i)g[i].clear(),dfn[i]=low[i]=scc[i]=;
sum=scc_cnt=;
while(!S.empty())S.pop();
while(m--){
scanf("%d%d",&u,&v);
g[u].pb(v);
}
for(i=;i<=n;++i){
if(!dfn[i]){
dfs(i);
}
}
if(scc_cnt==){
cout<<<<endl;
continue;
}
for(i=;i<=scc_cnt;++i)in[i]=out[i]=;
for(u=;u<=n;++u){
for(int v:g[u]){
if(scc[u]!=scc[v]){
in[scc[v]]=out[scc[u]]=;
}
}
}
int a=,b=;
for(i=;i<=scc_cnt;++i)a+=in[i],b+=out[i];
cout<<max(a,b)<<endl;
}
return ;
}
Kosaraju:先按原图跑一编按后序顺序编号,然后按照编号从大到小跑反向图,跑一次就是一个scc。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<map>
#include<set>
#include<stack>
#include<deque>
#include<bitset>
#include<unordered_map>
#include<unordered_set>
#include<queue>
#include<cstdlib>
#include<ctype.h>
#include<ctime>
#include<functional>
#include<algorithm>
#include<bits/stdc++.h>
using namespace std;
#define LL long long
#define pii pair<int,int>
#define mp make_pair
#define pb push_back
#define fi first
#define se second
#define inf 0x3f3f3f3f
#define debug puts("debug")
#define mid ((L+R)>>1)
#define lc (id<<1)
#define rc (id<<1|1)
const int maxn=;
const int maxm=;
const double PI=acos(-1.0);
const double eps=1e-;
const LL mod=1e9+;
LL gcd(LL a,LL b){return b==?a:gcd(b,a%b);}
LL lcm(LL a,LL b){return a/gcd(a,b)*b;}
LL qpow(LL a,LL b,LL c){LL r=; for(;b;b>>=,a=a*a%c)if(b&)r=r*a%c;return r;}
template<class T>
void prt(T v){for(auto x:v)cout<<x<<' ';cout<<endl;}
struct Edge{int u,v,w,next;}; int vis[maxn],scc[maxn],scc_cnt;
int in[maxn],out[maxn];
vector<int>g[maxn],g2[maxn],q;
void dfs1(int u){
if(vis[u])return;vis[u]=;
for(int v:g[u])dfs1(v);q.pb(u);
}
void dfs2(int u){
if(scc[u])return;scc[u]=scc_cnt;
for(int v:g2[u])dfs2(v);
}
int main(){
int t,n,m,i,j,k,u,v;
scanf("%d",&t);
while(t--){
scanf("%d%d",&n,&m);
q.clear();
for(i=;i<=n;++i)g[i].clear(),g2[i].clear(),vis[i]=scc[i]=;
scc_cnt=;
while(m--){
scanf("%d%d",&u,&v);
g[u].pb(v);
g2[v].pb(u);
}
for(i=;i<=n;++i){
if(!vis[i]){
dfs1(i);
}
}
for(i=n-;i>=;--i){
if(!scc[q[i]]){
++scc_cnt;
dfs2(q[i]);
}
}
// cout<<"FUCK: "<<scc_cnt<<endl;
if(scc_cnt==){
cout<<<<endl;
continue;
}
for(i=;i<=scc_cnt;++i)in[i]=out[i]=;
for(u=;u<=n;++u){
for(int v:g[u]){
if(scc[u]!=scc[v]){
in[scc[v]]=out[scc[u]]=;
}
}
}
int a=,b=;
for(i=;i<=scc_cnt;++i)a+=in[i],b+=out[i];
cout<<max(a,b)<<endl; }
return ;
}
HDU-2767-tarjan/Kosaraju求scc的更多相关文章
- tarjan算法求scc & 缩点
前置知识 图的遍历(dfs) 强连通&强连通分量 对于有向图G中的任意两个顶点u和v存在u->v的一条路径,同时也存在v->u的路径,我们则称这两个顶点强连通.以此类推,强连通分量 ...
- 转载 - Tarjan算法(求SCC)
出处:http://blog.csdn.net/xinghongduo/article/details/6195337 说到以Tarjan命名的算法,我们经常提到的有3个,其中就包括本文所介绍的求强连 ...
- HDU 2874 /// tarjan离线求森林里两点的距离
题目大意: 在一个森林里 询问 u v 两点 若不能到达输出 "Not connected" 否则输出两点距离 https://blog.csdn.net/keyboarderqq ...
- HDU 2586 /// tarjan离线求树上两点的LCA
题目大意: 询问一棵树里 u 到 v 的距离 可由 dis[ u到根 ] + dis[ v到根 ] - 2*dis[ lca(u,v) ] 得到 https://blog.csdn.net/csyzc ...
- 间谍网络——tarjan求SCC
洛谷传送门 看着这道题给人感觉就是tarjan求SCC,然而还得判断是否能控制全部间谍,这就得先从可以贿赂的点dfs一遍. 如果没有全部被标记了,就输出NO,再从没被标记的点里找最小的标号. 如果全被 ...
- tarjan 缩点 求 scc
算法学自 BYVoid https://www.byvoid.com/zhs/blog/scc-tarjan/ 这个写得很清楚了 当然 你可能不这么认为 而且 如果是让我 一开始就从这个博客 学 ta ...
- HDU 1269 -- 迷宫城堡【有向图求SCC的数目 && 模板】
迷宫城堡 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total Submi ...
- HDU 1269 迷宫城堡 tarjan算法求强连通分量
基础模板题,应用tarjan算法求有向图的强连通分量,tarjan在此处的实现方法为:使用栈储存已经访问过的点,当访问的点离开dfs的时候,判断这个点的low值是否等于它的出生日期dfn值,如果相等, ...
- 有向图 加最少的边 成为强连通分量的证明 poj 1236 hdu 2767
poj 1236: 题目大意:给出一个有向图, 任务一: 求最少的点,使得从这些点出发可以遍历整张图 任务二: 求最少加多少边 使整个图变成一个强连通分量. 首先任务一很好做, 只要缩点 之后 求 ...
随机推荐
- (转载)C#:Form1_Load()不被执行的三个解决方法
我的第一个c#练习程序,果然又出现问题了...在Form1_Load() not work.估计我的人品又出现问题了. 下面实现的功能很简单,就是声明一个label1然后,把它初始化赋值为hello, ...
- PTA 7-2 二叉搜索树的结构(30 分)
7-2 二叉搜索树的结构(30 分) 二叉搜索树或者是一棵空树,或者是具有下列性质的二叉树: 若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值:若它的右子树不空,则右子树上所有结点的值均大 ...
- 搭建springboot环境
1.前戏准备: SpringBoot核心jar包:这里直接从Spring官网下载了1.5.9版本. jdk:jdk1.8.0_45. maven项目管理工具:3.5版本. tomcat:8.5版本. ...
- 转载]SAP囚徒 - 通过销售订单领用到成本中心,FI替代
转载]SAP囚徒 - 通过销售订单领用到成本中心,FI替代 原文地址:SAP囚徒 - 通过销售订单领用到成本中心,FI替代实现不同成本中心记账科目不同作者:SAP囚徒 物品领用通常是库存管理的范畴 ...
- MInio python
# Install Minio library. # $ pip install minio # # Import Minio library. from minio import Minio # I ...
- android获取屏幕宽度和高度
1. WindowManager wm = (WindowManager) getContext() .getSystemService(Context.WINDOW_SERVICE); int wi ...
- Android 4.0之后的日历控件拥挤的解决办法
本意是想做成这个样子的控件: 发现使用datepicker之后,效果完全不同,把整个日历都显示出来了.非常拥挤. 在datepicker中加入android:calendarViewShown=&qu ...
- hdu 3832 Earth Hour bfs
Earth Hour Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 125536/65536 K (Java/Others) Prob ...
- python 传递多个参数
def oper(a,*args): print(args) print(a) oper("q","s","d","z" ...
- java 虹软ArcFace 2.0,java SDK使用-进行人脸检测
虹软产品地址:http://ai.arcsoft.com.cn/product/arcface.html虹软ArcFace功能简介 人脸检测人脸跟踪人脸属性检测(性别.年龄)人脸三维角度检测人脸对比 ...