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的更多相关文章

  1. tarjan算法求scc & 缩点

    前置知识 图的遍历(dfs) 强连通&强连通分量 对于有向图G中的任意两个顶点u和v存在u->v的一条路径,同时也存在v->u的路径,我们则称这两个顶点强连通.以此类推,强连通分量 ...

  2. 转载 - Tarjan算法(求SCC)

    出处:http://blog.csdn.net/xinghongduo/article/details/6195337 说到以Tarjan命名的算法,我们经常提到的有3个,其中就包括本文所介绍的求强连 ...

  3. HDU 2874 /// tarjan离线求森林里两点的距离

    题目大意: 在一个森林里 询问 u v 两点 若不能到达输出 "Not connected" 否则输出两点距离 https://blog.csdn.net/keyboarderqq ...

  4. HDU 2586 /// tarjan离线求树上两点的LCA

    题目大意: 询问一棵树里 u 到 v 的距离 可由 dis[ u到根 ] + dis[ v到根 ] - 2*dis[ lca(u,v) ] 得到 https://blog.csdn.net/csyzc ...

  5. 间谍网络——tarjan求SCC

    洛谷传送门 看着这道题给人感觉就是tarjan求SCC,然而还得判断是否能控制全部间谍,这就得先从可以贿赂的点dfs一遍. 如果没有全部被标记了,就输出NO,再从没被标记的点里找最小的标号. 如果全被 ...

  6. tarjan 缩点 求 scc

    算法学自 BYVoid https://www.byvoid.com/zhs/blog/scc-tarjan/ 这个写得很清楚了 当然 你可能不这么认为 而且 如果是让我 一开始就从这个博客 学 ta ...

  7. HDU 1269 -- 迷宫城堡【有向图求SCC的数目 &amp;&amp; 模板】

    迷宫城堡 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submi ...

  8. HDU 1269 迷宫城堡 tarjan算法求强连通分量

    基础模板题,应用tarjan算法求有向图的强连通分量,tarjan在此处的实现方法为:使用栈储存已经访问过的点,当访问的点离开dfs的时候,判断这个点的low值是否等于它的出生日期dfn值,如果相等, ...

  9. 有向图 加最少的边 成为强连通分量的证明 poj 1236 hdu 2767

    poj 1236: 题目大意:给出一个有向图, 任务一: 求最少的点,使得从这些点出发可以遍历整张图  任务二: 求最少加多少边 使整个图变成一个强连通分量. 首先任务一很好做, 只要缩点 之后 求 ...

随机推荐

  1. 论文阅读之:Deep Meta Learning for Real-Time Visual Tracking based on Target-Specific Feature Space

    Deep Meta Learning for Real-Time Visual Tracking based on Target-Specific Feature Space  2018-01-04  ...

  2. Kylin web界面 知识点介绍

    Big Data Era: 1.More and more data becoming available on Hadoop2.Limitations in existing Business ...

  3. 1、http协议基础及IO模型

    Nginx (web server,web reverse proxy): http协议:80/tcp,HyperText Transfer Procotol http协议版本: HTTP/0.9:原 ...

  4. Ajax - 汇总

    1,什么是ajax? 为什么要使用ajax? 1.ajax是"asynchornous javascript and xml "的缩写,指一种创建交互式网页应用的网页开发技术. 2 ...

  5. 主键非自增列 EF 插入数据库引起的 ID 列不能为 NULL 的错误

    protected override void OnModelCreating(DbModelBuilder modelBuilder) { modelBuilder.Entity<PostBo ...

  6. 项目Alpha冲刺——代码规范、冲刺任务与计划

    作业要求 这个作业属于哪个课程 软件工程1916-W(福州大学) 这个作业要求在哪里 项目Alpha冲刺 团队名称 基于云的胜利冲锋队 项目名称 云评:高校学生成绩综合评估及可视化分析平台 这个作业的 ...

  7. Missing artifact com.oracle:ojdbc6:jar:10.2.0.4.0问题解决 ojdbc包pom.xml出错

    遇到的问题:ojdbc.jar包出错 原因:因为oracle的ojdbc.jar是收费的,所以maven的中央仓库中没有这个资源,只能通过配置本地库才能加载到项目中去. 解决办法: (前提是安装好了m ...

  8. [原][粒子特效][spark]深入浅出osgSpark

    背景: 目前我使用的spark粒子特效库是2.0 这个库好像是原来鬼火引擎的一部分,需要从github上找 现在我要将其使用到我自己开发的基于osgearth开的三维地图引擎中 步骤: 1.编译spa ...

  9. TRMM数据在arcgis打开

    基本思路:地图配准 1将投影设置为plate carree(world) ,是在投影坐标系统下的世界中选择,当然为了输入坐标方便,设置属性genral中单位为度,显示为度分秒. 2 首先,要知道打开后 ...

  10. linux修改网卡名为eth0

    方法1: 1.编辑网卡的配置文件 vi /etc/sysconfig/network-scripts/ifcfg-ens33 将里面的NAME和DEVICE项修改为eth0,ONBOOT修改为yes. ...