poj2767,单向连通图判定,缩点+重新建图+新图DFS
/*该题被博客里标记为中等题,30分钟内1A,掌握了算法就简单了,单向连通图判定,单向连通图缩点
后必然唯一存在出度为0的点和入度为0的点,并且从入度为0的点出发,可以遍历所有点后到达出度为0点
(一条长链),(容易反证),所以缩点后,我重新建图(以前觉得重新建图好麻烦,现在看来SO easy),
,对新有向无环图,从入度为0的点做dfs(回溯时要标记回来,因为要所有dfs路线),有一条深度到达
强连通分支数即为yes,反之no*/
#include<iostream> //297MS, 1A,简单题。
#include<vector>
#include<cstdio>
#include<cstring>
#include<stack>
using namespace std;
int n;int m;
const int MAX=1001;
vector<vector<int> >edges(MAX); //原图
vector<vector<int> >newedge(MAX);//缩点后图
int visited[MAX]; //原图tarjan
int low[MAX];
int dfn[MAX];
bool mark[MAX]; //新图dfs标记
int Strongly_connected_branch[MAX]; //并为一个强连通,标记为1.2.3...
int num;int times;
stack<int>s;
bool instack[MAX];
int ind[MAX]; //入度数组
void tarjan(int u)
{
low[u]=dfn[u]=times++;
instack[u]=1;
s.push(u);
int len=edges[u].size();
for(int i=0;i<len;i++)
{
int v=edges[u][i];
if(visited[v]==0)
{
visited[v]=1;
tarjan(v);
if(low[u]>low[v])low[u]=low[v];
}
else if(instack[v]&&low[u]>dfn[v]) //有向图,要问是否在栈中,后向边,V为U某个祖先
{
low[u]=dfn[v];
}
}
if(dfn[u]==low[u]) //在一个SCC
{
num++;int temp;
do
{
temp=s.top();
instack[temp]=0;
s.pop();
Strongly_connected_branch[temp]=num;
} while(temp!=u);
}
}
bool is_no;
void dfs(int u,int depth) //新图的dfs
{
if(depth==num)is_no=true;
int len=newedge[u].size();
for(int i=0;i<len;i++)
{
int v=newedge[u][i];
if(mark[v]==0)
{
mark[v]=1;
dfs(v,depth+1);
mark[v]=0;
}
}
}
void readin()
{
scanf("%d%d",&n,&m);
int from,to;
for(int i=1;i<=m;i++)
{
scanf("%d%d",&from,&to);
edges[from].push_back(to);
}
}
void initialize() //初始化
{
is_no=num=times=0;
for(int i=0;i<=n;i++)
{
ind[i]=0;
mark[i]=instack[i]=low[i]=dfn[i]=visited[i]=0;
edges[i].clear();
newedge[i].clear();
Strongly_connected_branch[i]=-1;
}
}
void solve()
{
for(int i=1;i<=n;i++)
if(visited[i]==0)
{
visited[i]=1;
tarjan(i);
}
for(int i=1;i<=n;i++) //重新建图,不在同一个SCB的边留下即可。
{
int len=edges[i].size();
for(int j=0;j<len;j++)
{
int v=edges[i][j];
if(Strongly_connected_branch[v]!=Strongly_connected_branch[i]) //注意用SCB序号作代表元(新节点)来重新建图
{
ind[Strongly_connected_branch[v]]++;
newedge[Strongly_connected_branch[i]].push_back(Strongly_connected_branch[v]);
}
}
}
int is_0ind;
for(int i=1;i<=num;i++) //找到入度为0的点,做起点dfs
{
if(ind[i]==0)is_0ind=i;
}
mark[is_0ind]=1;
dfs(is_0ind,1);
if(is_no)printf("Yes\n");
else printf("No\n");
}
int main()
{
int tcase;
scanf("%d",&tcase);
while(tcase--)
{
initialize();
readin();
solve();
}
return 0;
}
poj2767,单向连通图判定,缩点+重新建图+新图DFS的更多相关文章
- POJ2762 单向连通图(缩点+拓扑排序
Going from u to v or from v to u? Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 19552 ...
- SCC重新建图
Tarjan或Kosaraju算法[对每个点归类belong]求出SCC之后,对num_scc个SCC重新建图,针对不同问题,考虑重边的问题. //************************** ...
- poj 2762 Going from u to v or from v to u?(强连通分量+缩点重构图+拓扑排序)
http://poj.org/problem?id=2762 Going from u to v or from v to u? Time Limit: 2000MS Memory Limit: ...
- hdoj 4612 Warm up【双连通分量求桥&&缩点建新图求树的直径】
Warm up Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65535/65535 K (Java/Others)Total Su ...
- HDU 1827 Summer Holiday(tarjan求强连通分量+缩点构成新图+统计入度+一点贪心思)经典缩点入门题
Summer Holiday Time Limit: 10000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)T ...
- hdu 2242 无向图/求用桥一分为二后使俩个bcc点权值和之差最小并输出 /缩点+2次新图dfs
题意如标题所述, 先无向图缩点,统计出每个bcc权,建新图,然后一遍dfs生成树,标记出每个点(新图)以及其子孙的权值之和.这样之后就可以dfs2来枚举边(原图的桥),更新最小即可. 调试了半天!原来 ...
- BZOJ 1179 抢掠计划atm (缩点+有向无环图DP)
手动博客搬家: 本文发表于20170716 10:58:18, 原地址https://blog.csdn.net/suncongbo/article/details/81061601 https:// ...
- 判断单向连通图(拓扑排序+tarjan缩点)
题意: 给你一个有向图,如果对于图中的任意一对点u和v都有一条从u到v的路或从v到u的路,那么就输出’Yes’,否则输出’No’. 理解:当出现两个及以上入度为0的点(有一个就可能是别人到它,有两个的 ...
- React Native 重新建项目遇到的一些问题
1.基本上一句话,就是本地的node太旧了,跟不上React_Native的节奏,所以需要更新node,但是单纯的更新node丫丫竟然不让我跟,因为是用Homebrew来管理的,所以先update了下 ...
随机推荐
- 最新版kubernetesV1.14.1集群一键自动部署脚本
部署命令如下:详情及注意事项请看README.md git clone https://github.com/luckman666/deploy_Kubernetes-v1.14.1.git cd d ...
- Java基础--java简介
1.Java的起源: Oak --> Java 2.Java的发展 Java1.0 Java2 JavaSE:Java平台标准版 JavaME:微型版 JavaEE:企业版 Sun公司 or ...
- TensorFlow 安装 Win10 Python+GPU
前叙:有灵魂的程序都是每一个程序员的最终目标.TensorFlow了解下? 打算花几个月学机器学习,TensorFlow是很好的选择,折腾了会环境,略有心得分享下. 环境:win10 Python:3 ...
- 什么是cookie(前段时间看到别人简历上把cookie和localStorage混淆了所以专门又去了解了下)
在前端面试中,有一个必问的问题:请你谈谈cookie和localStorage有什么区别啊? localStorage是H5中的一种浏览器本地存储方式,而实际上,cookie本身并不是用来做服务器存储 ...
- 1.1 NLP基础技能,字符串的处理
#!/usr/bin/env python # coding: utf-8 # # 字符串操作 # ### 去空格和特殊字符 # In[8]: s = " hello world! &quo ...
- Python3简明教程(九)—— 文件处理
文件是保存在计算机存储设备上的一些信息或数据.你已经知道了一些不同的文件类型,比如你的音乐文件,视频文件,文本文件.Linux 有一个思想是“一切皆文件”,这在实验最后的 lscpu 的实现中得到了体 ...
- DP || HYSBZ 1207 打鼹鼠
n*n的网格,有m个鼹鼠,t时间会有一只鼹鼠出现在(x,y)点处,如果机器人也在这个点就可以打到鼹鼠 机器人初始位置任意,每秒可以移动一格,问最多打到多少鼹鼠 *解法:f[i]表示前i只鼹鼠打了多少个 ...
- svn 设置代理
Memory4Young Do Not Repeat Yourself! SVN —— 如何设置代理 如果在使用SVN下载外网的资源时,出现这样的提示:No such host is known. 或 ...
- [题解] cogs 1669 神秘的咒语
http://cogs.pro:8080/cogs/problem/problem.php?pid=1669 "The Real Incantation is Their Common In ...
- STL 源码分析六大组件-allocator
1. allocator 基本介绍 分配器(allocator))是C ++标准库的一个组件, 主要用来处理所有给定容器(vector,list,map等)内存的分配和释放.C ++标准库提供了默认使 ...