poj 2186 强连通分支 和 spfa
思路:
建图时,分别建正向图edge和转置图T。用正向图edge来DFS,找出第一个被发现的强连通分支(如果该图存在题目要求的点,那么一定就是第一个被发现的)。然后用spfa跑转置图T,判断被发现的点是否可以到达所有点,如可以,就把该连通同的点数输出。否则输出0 。
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
#define Maxn 10100
#define Maxm Maxn*10
#define inf 0x7fffffff
using namespace std;
int index[Maxn],vi[Maxn],stack[Maxn],dfn[Maxn],low[Maxn],e,n,lab,top,num,E,Index[Maxn],Que[];
struct Edge{
int from,to,next;
}edge[Maxm],T[Maxm];
void addedge(int from,int to)
{
edge[e].from=from;
edge[e].to=to;
edge[e].next=index[from];
index[from]=e++;
T[E].from=to;
T[E].to=from;
T[E].next=Index[to];
Index[to]=E++;
}
void init()
{
memset(index,-,sizeof(index));
memset(Index,-,sizeof(Index));
memset(dfn,,sizeof(dfn));
memset(low,,sizeof(low));
memset(vi,,sizeof(vi));
e=lab=top=num=E=;
}
void Out(int u)//统计该连通分量点的个数
{
int i,j;
do{
i=stack[--top];
num++;
vi[i]=;
}
while(i!=u);
}
int dfs(int u)
{
dfn[u]=low[u]=++lab;
stack[top++]=u;
vi[u]=;
int i,j,temp;
for(i=index[u];i!=-;i=edge[i].next)
{
temp=edge[i].to;
if(!dfn[temp])
{
if(dfs(temp))
return ;
low[u]=min(low[u],low[temp]);
}
if(vi[temp])
low[u]=min(low[u],dfn[temp]);
}
if(low[u]==dfn[u])//一旦找到就不在寻找了,这样省了很多时间。
{
Out(u);
return ;
}
return ;
}
int spfa(int u)//判断是否全图可达
{
memset(vi,,sizeof(vi));
int i,temp;
int head,tail;
head=tail=;
vi[u]=;
Que[head++]=u;
while(head!=tail)
{
temp=Que[tail++];
vi[temp]=;
for(i=Index[temp];i!=-;i=T[i].next)
{
if(!vi[T[i].to])
{
vi[T[i].to]=;
Que[head++]=T[i].to;
}
}
}
for(i=;i<=n;i++)
if(!vi[i])
return ;
return ;
}
int main()
{
int m,i,j,a,b;
while(scanf("%d%d",&n,&m)!=EOF)
{
init();
for(i=;i<=m;i++)
{
scanf("%d%d",&a,&b);
addedge(a,b);
}
dfs();
if(spfa(stack[top]))
printf("%d\n",num);
else
printf("0\n");
}
return ;
}
在给个缩点的方法,将每次找到的连通分支全部标号为一样,这样每个连通分支就成了一个点,然后只要判断出度为0 的点的个数,如果只有一个,那么输出这个连通分量的点数,如果存在多个,则输出0 。
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
#define Maxn 10100
#define Maxm Maxn*10
#define inf 0x7fffffff
using namespace std;
int index[Maxn],vi[Maxn],stack[Maxn],dfn[Maxn],low[Maxn],e,n,lab,top,num,list,ans[Maxn],degree[Maxn],be[Maxn];
struct Edge{
int from,to,next;
}edge[Maxm];
void addedge(int from,int to)
{
edge[e].from=from;
edge[e].to=to;
edge[e].next=index[from];
index[from]=e++;
}
void init()
{
memset(index,-,sizeof(index));
memset(degree,,sizeof(degree));
memset(dfn,,sizeof(dfn));
memset(low,,sizeof(low));
memset(vi,,sizeof(vi));
memset(ans,,sizeof(ans));
memset(be,,sizeof(be));
e=lab=top=num=list=;
}
void Out(int u)
{
int i,j;
list++;
do{
i=stack[--top];
be[i]=list;
num++;
vi[i]=;
}
while(i!=u);
ans[list]=num;
}
int dfs(int u)
{
dfn[u]=low[u]=++lab;
stack[top++]=u;
vi[u]=;
int i,j,temp;
for(i=index[u];i!=-;i=edge[i].next)
{
temp=edge[i].to;
if(!dfn[temp])
{
dfs(temp);
low[u]=min(low[u],low[temp]);
}
if(vi[temp])
low[u]=min(low[u],dfn[temp]);
}
if(low[u]==dfn[u])
Out(u);
return ;
}
int solve()
{
int i,j,temp,cc=;
for(i=;i<=n;i++)
if(!dfn[i])
dfs(i);
for(i=;i<=n;i++)
{
for(j=index[i];j!=-;j=edge[j].next)
{
temp=edge[j].to;
if(be[i]!=be[temp])
{
degree[be[i]]=;
}
}
}
for(i=;i<=list;i++)
{
if(!degree[i])
{
cc++;
temp=i;
}
}
if(cc==)
{
return ans[temp];
}
else
return ;
return ;
}
int main()
{
int m,i,j,a,b;
while(scanf("%d%d",&n,&m)!=EOF)
{
init();
for(i=;i<=m;i++)
{
scanf("%d%d",&a,&b);
addedge(a,b);
}
printf("%d\n",solve());
}
return ;
}
poj 2186 强连通分支 和 spfa的更多相关文章
- poj 2049(二分+spfa判负环)
poj 2049(二分+spfa判负环) 给你一堆字符串,若字符串x的后两个字符和y的前两个字符相连,那么x可向y连边.问字符串环的平均最小值是多少.1 ≤ n ≤ 100000,有多组数据. 首先根 ...
- poj 2186 强连通分量
poj 2186 强连通分量 传送门 Popular Cows Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 33414 Acc ...
- 强连通分量分解 Kosaraju算法 (poj 2186 Popular Cows)
poj 2186 Popular Cows 题意: 有N头牛, 给出M对关系, 如(1,2)代表1欢迎2, 关系是单向的且能够传递, 即1欢迎2不代表2欢迎1, 可是假设2也欢迎3那么1也欢迎3. 求 ...
- POJ 3159 Candies(SPFA+栈)差分约束
题目链接:http://poj.org/problem?id=3159 题意:给出m给 x 与y的关系.当中y的糖数不能比x的多c个.即y-x <= c 最后求fly[n]最多能比so[1] ...
- POJ 3259 Wormholes(SPFA)
http://poj.org/problem?id=3259 题意 : 农夫约翰农场里发现了很多虫洞,他是个超级冒险迷,想利用虫洞回到过去,看再回来的时候能不能看到没有离开之前的自己,农场里有N块地, ...
- POJ 1860 Currency Exchange (SPFA松弛)
题目链接:http://poj.org/problem?id=1860 题意是给你n种货币,下面m种交换的方式,拥有第s种货币V元.问你最后经过任意转换可不可能有升值.下面给你货币u和货币v,r1是u ...
- POJ 2186 Popular Cows(强连通分量缩点)
题目链接:http://poj.org/problem?id=2186 题目意思大概是:给定N(N<=10000)个点和M(M<=50000)条有向边,求有多少个“受欢迎的点”.所谓的“受 ...
- poj 2186 Popular Cows (强连通分量+缩点)
http://poj.org/problem?id=2186 Popular Cows Time Limit: 2000MS Memory Limit: 65536K Total Submissi ...
- POj 2186 Popular Cows[连通分量]
题目大意:给出N头牛,有M种关系u, v.代表u牛崇拜v牛.要求找出有多少头牛被所有牛崇拜着题目链接:http://poj.org/problem?id=2186解题思路:1>求出强连通分量,标 ...
随机推荐
- Spring properties dependency checking
In Spring,you can use dependency checking feature to make sure the required properties have been set ...
- pygame简单动态图 & 动态图片的移动
之前在学pygame 时看了一些博客(来自http://eyehere.net/2011/python-pygame-novice-professional-plant-zombie-1/),觉得写得 ...
- U3D中的协同等待函数
WaitForSeconds.WaitForseconds等待函数; 创建一个yield指令,来等待给定的秒数; using UnityEngine; using System.Collections ...
- SSH登录失败:Host key verification failed
转载自:https://help.aliyun.com/knowledge_detail/41471.html 注意:本文相关 Linux 配置及说明已在 CentOS 6.5 64 位操作系统中进行 ...
- PostgreSQL的 initdb 源代码分析之二十五
继续分析: make_postgres(); 展开: 目的是创建postgres数据库. cmd是:/home/pgsql/project/bin/postgres" --single -F ...
- 2015南阳CCPC F - The Battle of Guandu 多源多汇最短路
The Battle of Guandu Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 无 Description In the year of 200, t ...
- HDU 4588 Count The Carries 数学
Count The CarriesTime Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://acm.hust.edu.cn/vjudge/contest/ ...
- android圆角View实现及不同版本这间的兼容(android3.0过后的版本)
http://blog.csdn.net/lovecluo/article/details/8710174 在做我们自己的APP的时候,为了让APP看起来更加的好看,我们就需要将我们的自己的View做 ...
- OpenStack Magnum 项目简单介绍
背景 Magnum 项目是 2014 年 11 月增加 OpenStack 的年轻项目,由 Rackspace主导发起,其定位是提供容器即服务(Container as a Service)的 API ...
- iOS开发——设备篇Swift篇&判断设备类型
判断设备类型 1,分割视图控制器(UISplitViewController) 在iPhone应用中,使用导航控制器由上一层界面进入下一层界面. 但iPad屏幕较大,通常使用SplitViewCo ...