图论1 Tarjan算法
强连通分量
模板(强联通分量个数+缩点)
- #include<iostream>
- #include<cstdio>
- #define MAXn 100000
- #define MAXm 2000000
- using namespace std;
- int dfn[MAXn],low[MAXn],head[MAXm],st[MAXn],belong[MAXn];
- bool in_st[MAXn];
- int ans,n,m,num,s_num,cnt,group_num;
- struct node{
- int to,pre;
- }e[MAXm];
- void Insert(int from,int to){
- e[++num].pre=head[from];
- e[num].to=to;
- head[from]=num;
- }
- void group(int u){
- cnt++;st[++s_num]=u;dfn[u]=low[u]=cnt;in_st[u]=;
- for(int i=head[u];i;i=e[i].pre){
- int v=e[i].to;
- if(!dfn[v]){
- group(v);
- if(low[v]<low[u])low[u]=low[v];
- }
- else if(dfn[v]<low[u])
- if(in_st[v])
- low[u]=dfn[v];
- }
- if(dfn[u]==low[u]){
- group_num++;
- while(st[s_num]!=u){
- in_st[st[s_num]]=;
- belong[st[s_num]]=group_num;
- s_num--;
- }
- in_st[u]=;s_num--;
- belong[u]=group_num;
- }
- }
- int main(){
- freopen("Tarjan_group.txt","r",stdin);
- scanf("%d%d",&n,&m);int x,y;
- for(int i=;i<=m;i++){
- scanf("%d%d",&x,&y);
- Insert(x,y);
- }
- for(int i=;i<=n;i++){
- if(!dfn[i])group(i);
- }
- for(int i=;i<=n;i++){
- printf("%d ",belong[i]);
- }printf("\n%d",group_num);
- }
Tarjan_group模板
例题
poj3114 Countries in War
跑一边强连通分量,搞出缩点,求缩点间的最短路
- #include<iostream>
- #include<cstdio>
- #include<cstring>
- using namespace std;
- #define maxm 250010
- #define maxn 510
- int head[maxm],dfn[maxn],low[maxn],st[maxn],belong[maxn],blong[maxn][maxn];
- int n,m,num,order,cnt,s_num,num_g,dis[maxn][maxn];
- int nw[][];
- bool in_st[maxn];
- struct node{
- int to,v,pre;
- }e[maxm];
- void Insert(int from,int to,int v){
- e[++num].to=to;
- e[num].pre=head[from];
- e[num].v=v;
- head[from]=num;
- }
- void group(int u){
- cnt++;dfn[u]=low[u]=cnt;st[++s_num]=u;in_st[u]=;
- for(int i=head[u];i;i=e[i].pre){
- int v=e[i].to;
- if(!dfn[v]){
- group(v);
- if(low[v]<low[u])low[u]=low[v];
- }
- else if(dfn[v]<low[u])
- if(in_st[v])low[u]=dfn[v];
- }
- if(low[u]==dfn[u]){
- num_g++;
- while(st[s_num]!=u){
- blong[num_g][++blong[num_g][]]=st[s_num];
- belong[st[s_num]]=num_g;
- in_st[st[s_num]]=;
- s_num--;
- }belong[u]=num_g;
- blong[num_g][++blong[num_g][]]=u;
- in_st[u]=;s_num--;
- }
- }
- int main(){
- freopen("Tarjan_group.txt","r",stdin);
- int nm,nn;
- while(){
- cin>>n>>m;
- if(n==&&m==)break;
- memset(dfn,,sizeof(dfn));
- memset(head,,sizeof(head));
- memset(low,,sizeof(low));
- memset(st,,sizeof(st));
- memset(e,,sizeof(e));
- memset(belong,,sizeof(belong));
- memset(blong,,sizeof(blong));
- num_g=;s_num=;cnt=;
- int x,y,z;
- memset(nw,/,sizeof(nw));
- memset(dis,/,sizeof(dis));
- for(int i=;i<=m;i++){
- scanf("%d%d%d",&x,&y,&z);
- Insert(x,y,z);
- nw[x][y]=z;
- }
- for(int i=;i<=n;i++){
- if(!dfn[i])group(i);
- }
- /*for(int i=1;i<=n;i++)
- cout<<belong[i]<<' ';cout<<endl<<endl;*/
- for(int i=;i<=n;i++){
- dis[i][i]=;
- nw[i][i]=;
- }
- for(int k=;k<=n;k++){
- for(int i=;i<=n;i++){
- for(int j=;j<=n;j++){
- if(i!=j&&i!=k&&k!=j)
- nw[i][j]=min(nw[i][j],nw[i][k]+nw[k][j]);
- }
- }
- }
- for(int i=;i<=num_g;i++){
- for(int j=;j<=num_g;j++){//找到两个缩点
- if(i!=j){
- for(int k=;k<=blong[i][];k++){
- for(int l=;l<=blong[j][];l++){
- if(k!=l)
- dis[i][j]=min(dis[i][j],nw[blong[i][k]][blong[j][l]]);
- }
- }
- }
- }
- }
- int p;
- scanf("%d",&p);
- for(int i=;i<=p;i++){
- scanf("%d%d",&x,&y);
- if(dis[belong[x]][belong[y]]>=)cout<<"Nao e possivel entregar a carta"<<endl;
- else cout<<dis[belong[x]][belong[y]]<<endl;
- }
- }
- }
TLE
- #include<cstring>
- #include<cstdio>
- #include<iostream>
- #define Max 505
- using namespace std;
- int map[Max][Max];
- struct Edge{
- int to,w;
- int next;
- }edge[Max * Max];
- int head[Max],tol;
- void add(int u,int v,int w){
- edge[tol].to=v;
- edge[tol].w=w;
- edge[tol].next=head[u];
- head[u]=tol++;
- }
- int dfn[Max],low[Max],Stack[Max],belong[Max];
- int bcnt,time,top,instack[Max];
- void tarjan(int u){
- dfn[u]=low[u]=++time;
- Stack[top++]=u;
- instack[u]=true;
- for(int i=head[u];i!=-;i=edge[i].next){
- int v=edge[i].to;
- if(!dfn[v]){
- tarjan(v);
- low[u] = min(low[u], low[v]);
- }
- else{
- if( instack[v])
- low[u] = min(low[u], dfn[v]);
- }
- }
- int v;
- if(low[u] == dfn[u]){
- bcnt++;
- do{
- v = Stack[--top];
- instack[v] = false;
- belong[v] = bcnt;
- }while(u != v);
- }
- }
- int main(){
- int n,m;
- int v,u,w;
- while(~scanf("%d%d", &n,&m)){
- if(!n && !m) break;
- memset(head,-,sizeof(head));
- tol=;
- for(int i=;i<=m;i++){
- int u,v,w;
- scanf("%d%d%d",&u,&v,&w);
- add(u,v,w);
- }
- memset(dfn,,sizeof(dfn));
- memset(low,,sizeof(low));
- top=time=bcnt=;
- for(int i=;i<=n;i++)
- if(!dfn[i])
- tarjan(i);
- for(int i=;i<=n;i++){
- for(int j=;j<=n;j++)
- if(i==j)
- map[i][j]=;
- else map[i][j]=0x3f3f3f3f;
- }
- for(u=;u<=n;u++) {
- for(int j=head[u];j!=-;j=edge[j].next) {
- v=edge[j].to;
- w=edge[j].w;
- if(belong[u]!=belong[v])
- map[belong[u]][belong[v]]=min(map[belong[u]][belong[v]],w);
- }
- }
- for(int k=;k<=bcnt;k++){
- for(int i=;i<=bcnt;i++){
- for(int j=;j<=bcnt;j++)
- if(map[i][j]>map[i][k]+map[k][j])
- map[i][j]=map[i][k]+map[k][j];
- }
- }
- int t;
- scanf("%d",&t);
- while(t--){
- scanf("%d%d",&u,&v);
- if(map[belong[u]][belong[v]] == 0x3f3f3f3f)
- printf("Nao e possivel entregar a carta\n");
- else
- printf("%d\n",map[belong[u]][belong[v]]);
- }
- printf("\n");
- }
- return ;
- }
AC
poj1236Network of Schools
题意:一个包含1-n号学校的网络,每个学校有个软件分发列表,当学校拿到软件时会把软件分发给列表里的学校。
问1:一个新软件出现时初始化情况至少需要给多少个学校才能让它到达整个网络?
问2:至少需要添加多少个名单才能使从任意一个学校开始分发都能充满整个网络?
也就是:
—给定一个有向图,求:
1) 至少要选几个顶点,才能做到从这些顶点出发,可以到达全部顶点
2) 至少要加多少条边,才能使得从任何一个顶点出发,都能到达全部顶点
DAG上面有多少个入度为0的顶点,问题1的答案就是多少
在DAG上要加几条边,才能使得DAG变成强连通的,问题2的答案就是多少
加边的方法:假定有 n 个入度为0的点,m个出度为0的点,max(m,n)就是第二个问题的解
- #include<iostream>
- #include<cstdio>
- using namespace std;
- #define maxn 110
- #define maxm (maxn*(maxn - 1)/2)
- int n,num,cnt,num_g,num_in0,num_out0;
- int in[maxn],out[maxn],head[maxm],belong[maxn],dfn[maxn],low[maxn],st[maxn],s_num;
- int blong[maxn][maxn],nmp[maxn][maxn];
- bool s_in[maxn],vis[maxn][maxn];
- struct node{
- int to,pre;
- }e[maxm];
- void Insert(int from,int to){
- e[++num].pre=head[from];
- e[num].to=to;
- head[from]=num;
- }
- void group(int u){
- cnt++;dfn[u]=low[u]=cnt;st[++s_num]=u;s_in[u]=;
- for(int i=head[u];i;i=e[i].pre){
- int v=e[i].to;
- if(dfn[v]==){
- group(v);
- low[u]=min(low[u],low[v]);
- }
- else if(dfn[v]){
- /*if(s_in[v])*/low[u]=min(low[u],dfn[v]);
- }
- }
- if(low[u]==dfn[u]){
- num_g++;
- while(st[s_num]!=u){
- s_in[st[s_num]]=;
- belong[st[s_num]]=num_g;
- blong[num_g][++blong[num_g][]]=st[s_num];
- s_num--;
- }
- s_num--;belong[u]=num_g;
- blong[num_g][++blong[num_g][]]=u;
- }
- }
- int main(){
- freopen("1236.txt","r",stdin);
- scanf("%d",&n);int a;
- for(int i=;i<=n;i++){
- while(){
- scanf("%d",&a);
- if(a==)break;
- Insert(i,a);
- }
- }
- for(int i=;i<=n;i++){
- if(dfn[i]==)group(i);
- }
- /*for(int i=1;i<=num_g;i++){//枚举每个缩点
- for(int j=1;j<=blong[i][0];j++){//枚举缩点里的每个点
- int u=i;
- for(int k=head[blong[i][j]];k;k=e[k].pre){
- int v=belong[e[k].to];
- if(vis[u][v]==0&&v!=u){
- vis[u][v]=1;in[v]++;out[u]++;
- }
- }
- }
- }*/
- for(int u=;u<=n;u++){
- for(int i=head[u];i;i=e[i].pre){
- int v=e[i].to;
- if(belong[u]!=belong[v]){
- in[belong[v]]++;
- out[belong[u]]++;
- }
- }
- }
- for(int i=;i<=num_g;i++){
- if(in[i]==)num_in0++;
- if(out[i]==)num_out0++;
- }
- cout<<num_in0<<endl;
- if(num_g==)cout<<;
- else cout<<max(num_in0,num_out0);
- return ;
- }
wa
图论1 Tarjan算法的更多相关文章
- 图论初步-Tarjan算法及其应用
暑假刷了一堆Tarjan题到头来还是忘得差不多. 这篇博客权当复习吧. 一些定义 无向图 割顶与桥 (划重点) 图G是连通图,删除一个点表示删除此点以及所有与其相连的边. 若删除某点u后G不再连通,那 ...
- 图论:Tarjan算法
在有向图中,若两点至少包含一条路径可以到达,则称两个顶点强连通,若任意两个顶点皆如此,则称此图为强联通图.非强连通图有向图的极大强连通子图,称为强连通分量(strongly connected com ...
- 『图论』有向图强连通分量的Tarjan算法
在图论中,一个有向图被成为是强连通的(strongly connected)当且仅当每一对不相同结点u和v间既存在从u到v的路径也存在从v到u的路径.有向图的极大强连通子图(这里指点数极大)被称为强连 ...
- 【算法•日更•第二十八期】图论:强连通+Tarjan算法(一)
▎前言 一直都想学习这个东西,以为很难,结果发现也不过如此. 只要会些图论的基础就可以了. ▎强连通 ☞『定义』 既然叫强连通,那么一定具有很强的连通性. 强连通:就是指在一个有向图中,两个顶点可以互 ...
- ACM(图论)——tarjan算法详解
---恢复内容开始--- tarjan算法介绍: 一种由Robert Tarjan提出的求解有向图强连通分量的线性时间的算法.通过变形,其亦可以求解无向图问题 桥: 割点: 连通分量: 适用问题: 求 ...
- 图论-强连通分量-Tarjan算法
有关概念: 如果图中两个结点可以相互通达,则称两个结点强连通. 如果有向图G的每两个结点都强连通,称G是一个强连通图. 有向图的极大强连通子图(没有被其他强连通子图包含),称为强连通分量.(这个定义在 ...
- Light OJ - 1026 - Critical Links(图论-Tarjan算法求无向图的桥数) - 带详细注释
原题链接 无向连通图中,如果删除某边后,图变成不连通,则称该边为桥. 也可以先用Tajan()进行dfs算出所有点 的low和dfn值,并记录dfs过程中每个 点的父节点:然后再把所有点遍历一遍 ...
- 强连通分量的Tarjan算法
资料参考 Tarjan算法寻找有向图的强连通分量 基于强联通的tarjan算法详解 有向图强连通分量的Tarjan算法 处理SCC(强连通分量问题)的Tarjan算法 强连通分量的三种算法分析 Tar ...
- tarjan算法 POJ3177-Redundant Paths
参考资料传送门 http://blog.csdn.net/lyy289065406/article/details/6762370 http://blog.csdn.net/lyy289065406/ ...
随机推荐
- Java for LeetCode 099 Recover Binary Search Tree
Two elements of a binary search tree (BST) are swapped by mistake. Recover the tree without changing ...
- 使用log4j将不同级别的日志信息输出到不同的文件中
使用log4j.xml xml格式的配置文件可以使用filter. 例如想只把log4j的debug信息输出到debug.log.error信息输出到error.log,info信息输出到info.l ...
- php基于swoole扩展的WebSocket
php的swoole的扩展可以实现WebSocket通信,方法如下 1.php添加swoole扩展: 一:两种安装方式:1>编译安装:1>wget http://pecl.php.net/ ...
- React Native 微信分享闪退的解决办法
Android中编写微信分享功能时出现了闪退的现象,经过几番资料的查找,发现是应用签名的问题,解决办法如下: 1. 进入微信官网的开放平台--->资源中心---->资源下载----& ...
- 跟我一起学Git (十) Patches【转】
本文转载自:http://cs-cjl.com/2014/05/05/learn_git_with_me_10 Git实现了以下三条用于交换patch的命令: git format-patch 用于创 ...
- python增删改查zabbix主机等
摘自: http://www.jianshu.com/p/e087cace8ddf 一.API简介 Zabbix API是在1.8版本中开始引进并且已经被广泛应用.所有的Zabbix移动客户端都是基于 ...
- RQNOJ 202 奥运火炬登珠峰:01背包
题目链接:https://www.rqnoj.cn/problem/202 题意: 登珠峰需要携带a(L)O2和t(L)N2. 有n个气缸可供选择.其中第i个气缸能装下a[i](L)O2和t[i](L ...
- tensorflow knn 预测房价 注意有 Min-Max Scaling
示例数据: 0.00632 18.00 2.310 0 0.5380 6.5750 65.20 4.0900 1 296.0 15.30 396.90 4.98 24.00 0.02731 0.00 ...
- UC Bug
出现bug时,假如把A代码段删了,bug消失,那么此bug是不是一定就是A代码段导致的呢?接着写B代码段,同样bug再现,那么此bug是不是一定就是B代码段导致的呢? 未必,可能是Base代码段和A. ...
- vue之webpack+vuecli打包生成资源相对引用路径与背景图片的正确引用
问题描述 一般情况下,通过webpack+vue-cli默认打包的css.js等资源,路径都是绝对的 但当部署到带有文件夹的项目中,这种绝对路径就会出现问题,因为把配置的static文件夹当成了根路径 ...