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>求出强连通分量,标 ...
随机推荐
- Codeforces 600B Queries about less or equal elements(二分查找)
Description You are given two arrays of integers a and b. For each element of the second array bj yo ...
- C#学习笔记(十一):动态类型
C#是一门静态类型的语言,但是在C#4.0时微软引入了动态类型的概念. dynamic 关键字dynamic用来定义动态对象,我们来看一下动态类型的一些特性. 调用不同类的相同方法 我们有两个或多个不 ...
- 新手一步一步OpenCV+Win7+Visual Studio 2013环境配置
地点:湖南大学软件大楼211 时间:2013.12.19 昨天导师布置了个任务,要求是找出用相机拍出同一移动场景下的两张照片,计算机能根据其中的差异计算场景移动的距离和旋转角度.据说以前很牛逼的师兄完 ...
- 【PYTHON】二维码生成
二维码是什么? 二维码从一维码扩展而来,增加另一维具有可读性的条码,用黑白矩形图形表示二进制数据,被设备扫描后获取其中包含的信息,二维码的长度.宽度均记载着数据,二维码具有定位点和容错机制,即便没有辨 ...
- 下载Xml文件方法
#region 下载Xml文件方法 //定义委托 private delegate void DownLoadDelegate(string url, string filename); privat ...
- [c++]this指针理解
#include <iostream> using namespace std; /** * this 指针理解 */ class A{ int i; public: void hello ...
- Ecshop实现注册页面手机号唯一的验证
前天,公司总监提了一个需求,实现我公司商城注册会员用手机号登录这个功能,那么这个功能容易修改,在我的前一篇博文中已经给出处理方法了,但是这里有一个问题,就是如果实现了用手机号码来登陆,那么就需要在注册 ...
- 深入Mysql 导入导出
mysql常用导出数据命令:1.mysql导出整个数据库 mysqldump -hhostname -uusername -ppassword databasename > backupfil ...
- 在Mac OS X 10.9上安装nginx
1. 安装PCRE Download latest PCRE. After download go to download directory from terminal. $ cd ~/Downlo ...
- TC srm 673 300 div1
TC srm.673 300 Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 Description 给你n(n<=50)匹马和n个人,一匹马和一个人能 ...