强连通分量(学习心得)

定义:有向图强连通分量:在有向图G中,如果两个顶点vi,vj间(vi>vj)有一条从vi到vj的有向路径,同时还有一条从vj到vi的有向路径,则称两个顶点强连通如果有向图G的每两个顶点都强连通,称G是一个强连通图。有向图的极大强连通子图,称为强连通分量。

求强连通分量:

vector<int>pic[maxn];
int dfn[maxn],low[maxn],ans[maxn];
bool ins[maxn];
stack<int>st;
int dind=0,block=0;
int siz[maxn],cud[maxn];
void tarjan(int x)
{dind++;dfn[x]=low[x]=dind;ins[x]=true;st.push(x);for (int j=0;j<pic[x].size();j++){int y=pic[x][j];if (dfn[y]==0){tarjan(y);low[x]=min(low[x],low[y]);}else if (ins[y]) low[x]=min(low[x],dfn[y]);}if (low[x]==dfn[x]){block++;siz[block]=0;while (true){int thi=st.top();st.pop();ans[thi]=block;siz[block]++;ins[thi]=false;if (thi==x) break;}}
}

  例题1【UVA-11324 最大团】

分析:先计算强连通分量,然后建一张新图,每个点的权值是它所包含的点的数量,求图的最长链。

代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<stack>
using namespace std;
const int maxn=1010;
vector<int> pic[maxn],new_[maxn];
int dfn[maxn],low[maxn],ans[maxn];
bool ins[maxn];
stack<int>st;
int dind=0,block=0;
int siz[maxn],dp[maxn],Ans;
void tarjan(int x)
{dind++;dfn[x]=low[x]=dind;ins[x]=true;st.push(x);for (int j=0;j<pic[x].size();j++){int y=pic[x][j];if (!dfn[y]){tarjan(y);low[x]=min(low[x],low[y]);}else if (ins[y]) low[x]=min(low[x],dfn[y]);}if (low[x]==dfn[x]){block++;siz[block]=0;while (true){int thi=st.top();st.pop();ans[thi]=block;siz[block]++;ins[thi]=false;if (thi==x) break;}}
}
int DP(int x){    if(dp[x]!=-1) return dp[x];int Max=0;  for(int i=0;i<new_[x].size();i++)  Max=max(Max,DP(new_[x][i]));  return dp[x]=siz[x]+Max;
}
void init(int n){for(int i=1;i<=n;i++) pic[i].clear(),new_[i].clear();memset(dfn,0,sizeof(dfn)); memset(low,0,sizeof(low));memset(ans,0,sizeof(ans)); memset(ins,0,sizeof(ins));while(!st.empty()) st.pop(); dind=block=Ans=0;memset(siz,0,sizeof(siz)); memset(dp,-1,sizeof(dp));
}
int main(){int n,m,N,u,v;scanf("%d",&N);while(N--){scanf("%d%d",&n,&m);init(n);while(m--){scanf("%d%d",&u,&v);pic[u].push_back(v);}for(int i=1;i<=n;i++)if(!dfn[i]) tarjan(i);for(int i=1;i<=n;i++)for(int j=0;j<pic[i].size();j++)if(ans[i]!=ans[pic[i][j]]) new_[ans[pic[i][j]]].push_back(ans[i]);for(int i=1;i<=block;i++) Ans=max(Ans,DP(i));printf("%d\n",Ans);}return 0;
}

  例题2【POJ 1236 学校网络】

第一问:缩点后求入度为0的结点数量;

第二问:对于一张有向无环图,可以通过把叶子结点连向根节点使它强连通;

like this:

所以需要连的边数量为max(叶节点,根节点);

叶节点是出度为0的点,根节点是入度为0的点;

注意当只有一个强连通分量时,需要特判,为0;

代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<stack>
#include<set>
using namespace std;
const int maxn=110;
vector<int> pic[maxn];
int dfn[maxn],low[maxn],ans[maxn];
bool ins[maxn];
stack<int>st;
set<int>check[maxn];
int dind=0,block=0;
int siz[maxn];
int ans1,in[maxn],out[maxn];void tarjan(int x)
{dind++;dfn[x]=low[x]=dind;ins[x]=true;st.push(x);for (int j=0;j<pic[x].size();j++){int y=pic[x][j];if (!dfn[y]){tarjan(y);low[x]=min(low[x],low[y]);}else if (ins[y]) low[x]=min(low[x],dfn[y]);}if (low[x]==dfn[x]){block++;siz[block]=0;while (true){int thi=st.top();st.pop();ans[thi]=block;siz[block]++;ins[thi]=false;if (thi==x) break;}}
}
int main(){int n,i,j;scanf("%d",&n);for(i=1;i<=n;i++){scanf("%d",&j);while(j) pic[i].push_back(j),scanf("%d",&j);	}for(int i=1;i<=n;i++)if(!dfn[i]) tarjan(i);for (i=1;i<=n;i++)for (j=0;j<pic[i].size();j++){int b1=ans[i],b2=ans[pic[i][j]];if (b1==b2) continue;if (check[b1].count(b2)) continue;check[b1].insert(b2);in[b2]++; out[b1]++;}int root=0,leaf=0;for(int i=1;i<=block;i++){if(!in[i]) root++;if(!out[i]) leaf++;}printf("%d\n",root);if(block==1) printf("0");else printf("%d",max(leaf,root));return 0;
}

  类似的还有【HDU 2767】

很奇怪的是提交时出现了这样尴尬的问题:

0_0_20950778_21662.cpp
0_0_20950778_21662.cpp(29) : error C3861: “min”:  找不到标识符
0_0_20950778_21662.cpp(31) : error C3861: “min”:  找不到标识符
0_0_20950778_21662.cpp(83) : error C3861: “max”:  找不到标识符

然后在出错的库后面加上了#include "minmax.h",就过了?(莫名其妙)

代码:

#include<iostream>
#include "minmax.h" 
#include<cstdio>
#include<cstring>
#include<vector>
#include<stack>
#include<set>
using namespace std;
const int maxn=20010;
vector<int> pic[maxn];
int dfn[maxn],low[maxn],ans[maxn];
bool ins[maxn];
stack<int>st;
set<int>check[maxn];
int dind=0,block=0,siz[maxn];
int in[maxn],out[maxn],T;
void tarjan(int x)
{dind++;dfn[x]=low[x]=dind;ins[x]=true;st.push(x);for (int j=0;j<pic[x].size();j++){int y=pic[x][j];if (!dfn[y]){tarjan(y);low[x]=min(low[x],low[y]);}else if (ins[y]) low[x]=min(low[x],dfn[y]);}if (low[x]==dfn[x]){block++;siz[block]=0;while (true){int thi=st.top();st.pop();ans[thi]=block;siz[block]++;ins[thi]=false;if (thi==x) break;}}
}
void init(int n){for(int i=1;i<=n;i++)  pic[i].clear(),check[i].clear();;memset(dfn,0,sizeof(dfn)); memset(low,0,sizeof(low));memset(ans,0,sizeof(ans)); memset(ins,0,sizeof(ins));while(!st.empty()) st.pop(); dind=0;block=0; memset(siz,0,sizeof(siz));memset(in,0,sizeof(in)); memset(out,0,sizeof(out));
}
int main(){scanf("%d",&T);while(T--){int n,i,j,m;scanf("%d%d",&n,&m);init(n);for(i=1;i<=m;i++){int x,y;scanf("%d%d",&x,&y);pic[x].push_back(y);	}for(int i=1;i<=n;i++)if(!dfn[i]) tarjan(i);for (i=1;i<=n;i++)for (j=0;j<pic[i].size();j++){int b1=ans[i],b2=ans[pic[i][j]];if (b1==b2) continue;if (check[b1].count(b2)) continue;check[b1].insert(b2);in[b2]++; out[b1]++;}int root=0,leaf=0;for(int i=1;i<=block;i++){if(!in[i]) root++;if(!out[i]) leaf++;}if(block==1) printf("0\n");else printf("%d\n",max(leaf,root));}return 0;
}

  ————————————————————————————————————————————————————————

 来自Paper Cloud的博客,未经允许,请勿转载,谢谢

转载于:https://www.cnblogs.com/PaperCloud/p/7113385.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/258134.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

java for的增强_Java基础之增强for循环

平时大家for循环应该用的不少&#xff0c;特别是增强for循环&#xff0c;简单快捷。但是在增强for中做删除操作&#xff0c;却会抛出java.util.ConcurrentModificationException&#xff0c;一起来看下。上面的代码&#xff0c;在for循环执行完if中的remove&#xff0c;遍历下一…

lintcode:递归打印数字

题目 用递归打印数字 用递归的方法找到从1到最大的N位整数。 样例 给出 N 1, 返回[1,2,3,4,5,6,7,8,9]. 给出 N 2, 返回[1,2,3,4,5,6,7,8,9,10,11,...,99]. 注意 用下面这种方式去递归其实很容易&#xff1a; recursion(i) {if i > largest number:returnresults.add(i)r…

做免费的EDM,EmailCar看中的是挖掘数据的价值

从2008年开始&#xff0c;做了9年企业级EDM&#xff08;电子邮件营销&#xff09;服务的陆霏近日宣布&#xff0c;他们的产品EmailCar从4.0版本开始永久免费为企业提供电子邮件基础投递业务。 我们电子邮箱经常收到的推广邮件就属于EDM&#xff0c;即Email Direct Marketing。这…

java 读取split_Java报错系列——split

在String中,split方法如下&#xff1a;可见&#xff0c;split的核心在于Pattern.compile(regex).split(this, limit);Java提供Pattern,Matcher用于支持正则&#xff0c;可以看一个例子&#xff1a;运行结果是&#xff1a;0,1||3,4|ab|7,8|cef|8,9||11,12|kk|13,14|a|需要注意的…

VS2012生成事件

Visual Studio 事件生成功能对我们开发综合项目的过程中尤为重要。 下面以VS2012为例&#xff1a; 选择工程-> 属性->编译->生成事件 包括两个生成事件&#xff1a;预先生成事件和后期生成事件 直接在相应的文本框里编写写脚本即可&#xff0c;如&#xff1a;编译完成…

H3C Navigate 2017 | 拉近世界的距离 新华三的泛联接版图

就今天而言&#xff0c;联接世界的网络外延已经无限扩大&#xff0c;联接的方式也越来越复杂。从互联网时代的PC互联&#xff0c;演进到移动互联网时代手机等移动终端的互联&#xff0c;而即将大规模爆发的物联网应用时代&#xff0c;所有的事物都可能被连入网络&#xff0c;一…

大数据时代的公共安全治理

未来&#xff0c;大数据将成为社会基础设施的一部分&#xff0c;跟公路、自来水、电一样&#xff0c;成为人们生活不可或缺的一部分。但大数据的作用并不仅仅局限于为普通消费者提供生活必须服务&#xff0c;它已经开始在信息产业、公共安全、交通运输、金融、水利等领域中发挥…

CCNA第二讲笔记

网络定义&#xff1a;一组由介质&#xff08;线缆&#xff09;互联的网络设备&#xff08;路由器、交换机&#xff09;和终端系统&#xff08;PC&#xff09;&#xff1b; 工作组&#xff1a;局域网范畴&#xff0c;范围最小的局域网&#xff0c;且不涉及网络设备。台式机需要有…

服务器资源管理器视图的添加显示的步骤

MVC视图查看数据库表结构时&#xff0c;通常会打开服务器资源管理器视图&#xff0c;在服务器资源管理器视图中能查看表的数据集及表结构 打开的方法为&#xff1a; ①可使用快捷键&#xff1a; ctrlaltS ②也可添加“服务器资源管理器视图”到“视图”工具菜单&#xff0c;做法…

能源局将提高光伏“领跑者”项目技术指标

记者从权威渠道获悉&#xff0c;国家能源局正计划对光伏“领跑者”中有关单多晶的转换效率标准等细节进行修改。“领跑者”计划中&#xff0c;光电转换效率的修订工作将在今年3月底展开&#xff0c;主要向各大相关机构、企业征求意见&#xff0c;如果争议较多&#xff0c;定稿时…

SlidingMenu的使用,结合Fragment(eclipse环境)

首先下载SlidingMenu&#xff0c;有Library和Sample&#xff0c;然后在自己的项目中引入类库&#xff08;引入智慧北京工作空间的Library&#xff09;&#xff0c;然后V4包会发生冲突&#xff0c;删掉自己项目Libs目录下的V4包即可 侧滑布局和主界面布局都先用一个空布局填充一…

java如何做全局缓存_传智播客JNI第七讲 – JNI中的全局引用/局部引用/弱全局引用、缓存jfieldID和jmethodID的两种方式...

讲解JNI中的全局引用/局部引用/弱全局引用、缓存jfieldID和jmethodID的两种方式&#xff0c;并编写两种缓存方式的示例代码。1.从Java虚拟机创建的对象传到本地C/C代码时会产生引用&#xff0c;根据Java的垃圾回收机制&#xff0c;只要有引用存在就不会出发该引用指向的Java对象…

C#设计模式学习笔记-单例模式

C#设计模式学习笔记-单例模式 最近在学设计模式&#xff0c;学到创建型模式的时候&#xff0c;碰到单例模式&#xff08;或叫单件模式&#xff09;&#xff0c;现在整理一下笔记。 在《Design Patterns&#xff1a;Elements of Resuable Object-Oriented Software》中的定义是&…

Linux 安装loadrunner 碰到的问题

关于linux下面搭建loadrunner的详细步骤&#xff1a; http://blog.sina.com.cn/s/blog_9aa583cf0101bu4y.html http://hi.baidu.com/higkoo/item/d75027acc78bab3e030a4dde?qq-pf-topcqq.c2c http://www.cnblogs.com/xiaoTT/archive/2012/02/15/2352127.html 用控制台加载负载…

数据分析真的能驱动用户快速增长吗?

俗话说&#xff0c;“酒香不怕巷子深”;俗话又说&#xff0c;“酒香也怕巷子深” 。再后来&#xff0c;俗话还说&#xff0c;管他酒香不香巷子深不深&#xff0c;只要找个算盘技巧神乎其神的账房先生&#xff0c;即数据科学家&#xff0c;酒就可以大卖了。这叫做用数据驱动用户…

解决启动Biee控制台乱码问题

解决启动Biee控制台乱码问题 在安装完Biee后&#xff0c;大家都可以看到在程序中可以找到启动BI服务的地方 点击上图中的启动bi服务则在window系统中会弹出一个dos窗口&#xff0c;来显示执行启动服务的操作&#xff0c;如下图 上图显示的是正常情况&#xff0c;本人安装后首次…

“北航Clubs” Alpha版发布!

一、功能 1.获取活动信息&#xff1a; 用户进入网站后&#xff0c;第一眼就可以查看到近期活动 2.查看活动详情 点击活动标题&#xff0c;可以进入活动详情页面 3.注册功能 首页点击注册&#xff0c;输入学号、密码、姓名、手机号即可完成注册 4.用户登陆 拥有账号之后&#xf…

Foundation框架

1.框架是由许多类、方法、函数、文档按照一定的逻辑组织起来的集合&#xff0c;以便使研发程序变的更容易 清除缓存&#xff0c;删除这个文件夹下的所有文件/Users/fanyafang/Library/Developer/Xcode/DerivedData 显示隐藏文件&#xff1a;defaults write com.apple.finder Ap…

转换php script类型,javascript如何实现值的类型转换

本篇文章给大家介绍使用javascript进行值的类型转换的方法&#xff0c;有一定的参考价值&#xff0c;有需要的朋友可以参考一下&#xff0c;希望对你们有所帮助。JavaScript是松散类型的语言&#xff0c;大多数情况下&#xff0c;运算符和函数会自动将值转换为正确的类型(隐式转…