1.迷宫城堡

题意:给一个图判断是否是强连通图。
题解:利用Tarjan计算图中强连通分量的个数,如果为1则是强连通图,否则不是。

#include<bits/stdc++.h>using namespace std;
const int N = 2e4+100;
typedef long long ll;
vector<int> G[N];
bool is_instack[N];
int dfn[N],low[N];
stack<int> sta;
int n,m,index,scc;
void init(){index=scc=0;memset(dfn,0,sizeof(dfn));memset(low,0,sizeof(low));memset(is_instack,0,sizeof(is_instack));while(!sta.empty()) sta.pop();for(int i=1;i<=n;i++) G[i].clear();
}
void Tarjan(int u){dfn[u]=low[u]=++index;sta.push(u);is_instack[u]=1;for(auto v:G[u]){if(!dfn[v]){Tarjan(v);low[u]=min(low[u],low[v]);}else if(is_instack[v]){low[u]=min(low[u],dfn[v]);}}if(low[u]==dfn[u]){++scc;while(sta.top()!=u){is_instack[sta.top()]=0;sta.pop();}}
}
int main(){while(scanf("%d %d",&n,&m)){if(n+m==0) break;init();int u,v;for(int i=0;i<m;i++){scanf("%d %d",&u,&v);G[u].push_back(v);}for(int i=1;i<=n;i++){if(!dfn[i]) Tarjan(i);}if(scc==1) puts("Yes");else puts("No");}return 0;
}

2.Proving Equivalences

题意:给定一个有向图,求最少加几条有向边使得整个图成为强连通。
题解:Tarjan缩点之后计算入读为000的个数aaa和出度为000的个数bbb,取最大值max(a,b)max(a,b)max(a,b),注意如果已经是强连通图了,则答案为000.

#include<bits/stdc++.h>using namespace std;
const int N = 1e5+100;
vector<int> G[N],color[N];
stack<int> sta;
int dfn[N],low[N];
int id[N],od[N];
bool is_instack[N];
int scc[N],nscc,index;
int n,m;
void init(){nscc=index=0;memset(scc,0,sizeof(scc));memset(dfn,0,sizeof(dfn));memset(id,0,sizeof(id));memset(od,0,sizeof(od));memset(is_instack,0,sizeof(is_instack));memset(low,0,sizeof(low));for(int i=1;i<=n;i++) G[i].clear(),color[i].clear();while(!sta.empty()) sta.pop();
}
void Tarjan(int u){low[u]=dfn[u]=++index;sta.push(u);is_instack[u]=1;for(auto v:G[u]){if(!dfn[v]){Tarjan(v);low[u]=min(low[u],low[v]);}else if(is_instack[v]){low[u]=min(low[u],dfn[v]);}}if(low[u]==dfn[u]){++nscc;while(1){int temp=sta.top();scc[temp]=nscc;sta.pop();is_instack[temp]=0;if(temp==u) break;}}
}
int main(){int T;scanf("%d",&T);while(T--){scanf("%d %d",&n,&m);init();int u,v;for(int i=1;i<=m;i++){scanf("%d %d",&u,&v);G[u].push_back(v);}for(int i=1;i<=n;i++){if(!dfn[i]) Tarjan(i);}//cerr<<nscc<<endl;if(nscc==1){puts("0");} else{for(int i=1;i<=nscc;i++) id[i]=od[i]=1;for(int i=1;i<=n;i++){for(auto j:G[i]){if(scc[i]!=scc[j]){id[scc[j]]=od[scc[i]]=0;}}} int n1=0;int n2=0;for(int i=1;i<=nscc;i++){n1+=id[i];n2+=od[i];}printf("%d\n",max(n1,n2));}}return 0;
}

3.Summer Holiday

题意:给你一个有向图,每个点都有一个权值,你需要在这个图中选择几个点使得利用这几个点可以遍历完整个图,同时还要满足选择的这几个点的权值和最小。
题解:Tarjan缩点,然后在缩点的时候把点的权值缩成所在的强连通分量里面权值最小的,然后寻找入度为0的点的个数,即为答案。

#include<bits/stdc++.h>using namespace std;
const int N = 1e5+100;
typedef long long ll;
const int INF = 0x3f3f3f3f;
int n,m,scc,index;
vector<int> G[N];
ll w[N],low[N],dfn[N],minn[N],color[N],id[N];
bool is_instack[N];stack<int> sta;
void init(){scc=index=0;memset(low,0,sizeof(low));memset(dfn,0,sizeof(dfn));memset(color,0,sizeof(color));memset(minn,INF,sizeof(minn));memset(is_instack,0,sizeof(is_instack));for(int i=1;i<=n;i++) G[i].clear();while(!sta.empty()) sta.pop();
}
void Tarjan(int u){low[u]=dfn[u]=++index;sta.push(u);is_instack[u]=1;for(auto v:G[u]){if(!dfn[v]){Tarjan(v);low[u]=min(low[u],low[v]);}else if(is_instack[v]){low[u]=min(low[u],dfn[v]);}}if(low[u]==dfn[u]){++scc;while(1){int temp=sta.top();color[temp]=scc;minn[scc]=min(minn[scc],w[temp]);is_instack[temp]=0;sta.pop();if(temp==u) break;}}
}
int main(){while(scanf("%d %d",&n,&m)!=EOF){init();for(int i=1;i<=n;i++) scanf("%lld",&w[i]);int u,v;for(int i=1;i<=m;i++){scanf("%d %d",&u,&v);G[u].push_back(v);         }for(int i=1;i<=n;i++){if(!dfn[i]) Tarjan(i);}for(int i=1;i<=scc;i++) id[i]=1;for(int i=1;i<=n;i++){for(auto j:G[i]){if(color[i]!=color[j]){id[color[j]]=0;}}}ll ans1,ans2;ans1=ans2=0;for(int i=1;i<=scc;i++){if(id[i]){ans1++;ans2+=minn[i];}}printf("%lld %lld\n",ans1,ans2);}return 0;
}

4.Intelligence System

题意:一个人际关系网,0号可以联系上任意一个人,如果两个人可以直接或间接的互相联系,那么这两个人的消费为0,求0号要联系上每个人最小的消费。
题解: Tarjan缩点,求最小树形图,由于题目保证有解,因此只需要统计每个点入边权值最小的即可。0所在的强连通分量不用考虑。

#include<bits/stdc++.h>using namespace std;
const int N = 50005    ;
typedef long long ll;
const ll INF = 0x3f3f3f3f;
ll low[N],dfn[N],minn[N],color[N];
bool  is_instack[N];
ll n,m,scc,index;
stack<ll> sta;
vector<pair<ll,ll> > G[N];
void init(){scc=index=0;for(int i=0;i<=n;i++){is_instack[i]=0;low[i]=0;dfn[i]=0;minn[i]=INF;G[i].clear();}while(!sta.empty()) sta.pop();
}
void Tarjan(ll u){low[u]=dfn[u]=++index;is_instack[u]=1;sta.push(u);for(auto V:G[u]){ll v=V.first;if(!dfn[v]){Tarjan(v);low[u]=min(low[u],low[v]);}else if(is_instack[v]){low[u]=min(low[u],dfn[v]);}}if(low[u]==dfn[u]){scc++;while(1){ll temp=sta.top();color[temp]=scc;is_instack[temp]=0;sta.pop();if(temp==u) break;}}
}
int main(){while(scanf("%lld %lld",&n,&m)!=EOF){map<pair<ll,ll>,ll> WW;//pair<ll,ll> pnow;init();ll u,v,w;for(ll i=1;i<=m;i++){scanf("%lld %lld %lld",&u,&v,&w);//pnow.first=u;pnow.second=v;//if(!WW[pnow]) WW[pnow]=w;//else WW[pnow]=min(WW[pnow],w);G[u].push_back(make_pair(v,w));}long long ans=0;for(ll i=0;i<n;i++){if(!dfn[i]) Tarjan(i);}for(ll i=0;i<n;i++){for(auto j:G[i]){ll x=color[i];ll y=color[j.first];if(x!=y) minn[y]=min(minn[y],(ll)j.second);}}for(ll i=1;i<=scc;i++){if(i!=color[0]) ans+=minn[i];}printf("%lld\n",ans);}return 0;
}

Tarjan算法专练相关推荐

  1. 图论——强连通分量(Tarjan算法)

    文章目录 强连通分量 利用Tarjan算法求强连通分量 来一道例题练手(USACO08DEC) 图论文章汇总 强连通分量 什么是强连通图? 如果一个有向图中,存在一条回路,所有的结点至少被经过一次,这 ...

  2. tarjan算法不是很懂先mark一下。

     前面为转载的.后面是自己的理解. 三种tarjan算法(上) .这篇算是做一个总结吧. 求强连通分量 求无向图的割和桥 最近公共祖先 求强连通分量 基本概念:       强连通是有向图才有的概念. ...

  3. Tarjan算法应用 (割点/桥/缩点/强连通分量/双连通分量/LCA(最近公共祖先)问题)...

    转载自:http://hi.baidu.com/lydrainbowcat/blog/item/2194090a96bbed2db1351de8.html 基本概念: 1.割点:若删掉某点后,原连通图 ...

  4. 0x66.图论 - Tarjan算法与无向图连通性

    目录 一.无向图的割点与桥 割点 桥/割边 时间戳 搜索树 追溯值 二.割边判定法则 三.割点判定法则 1.luogu P3388 [模板]割点(割顶) 2.luogu P3469 [POI2008] ...

  5. 『Tarjan算法 无向图的双联通分量』

    无向图的双连通分量 定义:若一张无向连通图不存在割点,则称它为"点双连通图".若一张无向连通图不存在割边,则称它为"边双连通图". 无向图图的极大点双连通子图被 ...

  6. Tarjan算法学习笔记

    一种由Robert Tarjan提出的求解有向图强连通分量的线性时间的算法. [有向图强连通分量] 在有向图G中,如果两个顶点间至少存在一条路径,称两个顶点强连通(strongly connected ...

  7. 『追捕盗贼 Tarjan算法』

    追捕盗贼(COCI2007) Description 为了帮助警察抓住在逃的罪犯,你发明了一个新的计算机系统.警察控制的区域有N个城市,城市之间有E条双向边连接,城市编号为1到N. 警察经常想在罪犯从 ...

  8. 算法提高课-图论-有向图的强连通分量-AcWing 367. 学校网络:强连通分量、tarjan算法

    文章目录 题目解答 题目来源 题目解答 来源:acwing 分析: 第一问:通过tarjan算法求出强连通分量并且缩点后,统计入度为0的点的个数p即可. 第二问,至少加几条边才能使图变成强连通分量?这 ...

  9. CSP认证201509-4 高速公路[C++题解]:强连通分量、tarjan算法模板题

    题目分析 来源:acwing 分析: 所求即为强连通分量的个数,然后计算每个强连通分量中点的个数,相加即可. 所谓强连通分量,它是一个子图,其中任意两点可以相互到达,并且再加一个点,就不能满足任意两点 ...

最新文章

  1. 深入了解 TabNet :架构详解和分类代码实现
  2. 谷歌将AutoML应用于Transformer架构,翻译结果飙升,已开源
  3. 世界一流大学如何建设人工智能学科
  4. 量子计算机个人化时间,科学家发现量子算法可以停止时间
  5. expected unqualified-id before numeric constant问题原因
  6. Java内存数据库-H2介绍及实例(SpringBoot)
  7. 理解WebKit和Chromium: Chromium for Android
  8. 真相了!算法工程师的一天
  9. 大牛书单 | 消息队列方向的好书
  10. T-SQL编程基础之二:条件选择、循环编程
  11. 容易忽视但是功能灰常强大的Java API(五. 二分查找)
  12. FreeRTOS--堆内存管理(二)
  13. ARM体系结构与汇编指令
  14. Java-break-continue
  15. mysql面试题 真的很不错
  16. Windows系统封装(四)正式封装和测试。
  17. pixi的使用之创建和操作精灵
  18. python学习——电子邮件
  19. 全面了解风控指标体系
  20. npm install xxx 出现Unexpected token < in

热门文章

  1. android 环信录音,环信音视频插件
  2. PWM的基本原理及其应用实例
  3. 声纹采集器和声纹数据库在公安领域的应用
  4. 第一行代码第二版6.4.1小节创建数据库中遇到adb shell出错的问题
  5. BUUCTF Quoted-printable编码
  6. 计算机组成原理学习笔记——机器指令的基本结构
  7. 年轻人租房大数据报告(人群画像).pdf
  8. (第39册)《微信小程序游戏开发快速入门到实战》夏敏捷著
  9. 区块链是什么通俗解释_区块链是什么?如何用一句话通俗解释区块链
  10. 计算机如何磁盘整理,如何整理磁盘碎片让Win7电脑运行更快?