博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
洛谷P2341 受欢迎的牛——Tarjan+缩点模板
阅读量:5124 次
发布时间:2019-06-13

本文共 1863 字,大约阅读时间需要 6 分钟。

又是一道Tarjan水题,这次经过仔细的思考,没有打错邻接表(图论已入门qwq)。

还是先来说说思路吧,由题意知,就是给一张n个点,m条边的有向图,让你求出有多少个点可以由所有的点达到。

有如下定理:若在有向图中有且仅有一个点出度为零,那么所有点都可达到它(传说中的反证法可以证明它(真的吗,我没证出来,逃))。

但是这是一个点啊,怎么搞出所有点呢?注意先前的论述中,有“所有点可达”这一字样,那么什么算法中还有这些字呢(模拟暴搜除外)?当然是强连通们啊!!!所以本题的思路就很明确了:Tarjan求强连通(别的也行),再缩点,在缩过点的邻接表中统计出度为零的点。

具体操作呢?看代码呗qwq。

#include
using namespace std;#define maxn 50005struct Edge{ int u,v;}e[maxn<<1],e2[maxn<<1];int first[maxn],next[maxn<<1],first2[maxn],next2[maxn<<1],cnt=0,cnt2=0;int out[10005];void AddEdge(int u,int v){ e[++cnt].u=u;e[cnt].v=v; next[cnt]=first[u];first[u]=cnt;}void AddEdge2(int u,int v){ e2[++cnt2].u=u;e2[cnt2].v=v; next2[cnt2]=first2[u];first2[u]=cnt2;}int pre[maxn],lowlink[maxn],sccno[maxn],dfs_clock,scc_cnt;stack
S;void Tarjan(int u){ pre[u]=lowlink[u]=++dfs_clock; S.push(u); for(int i=first[u];i;i=next[i]){ int v=e[i].v; if(!pre[v]){ Tarjan(v); lowlink[u]=min(lowlink[u],lowlink[v]); } else if(!sccno[v]){ lowlink[u]=min(lowlink[u],pre[v]); } } if(lowlink[u]==pre[u]){ scc_cnt++; for(;;){ int x=S.top(); S.pop(); sccno[x]=scc_cnt; if(x==u) break; } }}void find_scc(int n){ memset(pre,0,sizeof(pre)); memset(sccno,0,sizeof(sccno)); for(int i=1;i<=n;i++) if(!pre[i]) Tarjan(i);}int main(){ int n,m; scanf("%d%d",&n,&m); for(int i=1;i<=m;i++){ int u,v; scanf("%d%d",&u,&v); AddEdge(u,v); } find_scc(n); for(int i=1;i<=n;i++) for(int j=first[i];j;j=next[j]) if(sccno[i]!=sccno[e[j].v]) AddEdge2(sccno[i],sccno[e[j].v]); for(int i=1;i<=scc_cnt;i++) for(int j=first2[i];j;j=next[j]) out[i]++; int ans=0,star=0,num=0; for(int i=1;i<=scc_cnt;i++) if(!out[i]){ num++; star=i; } if(num==1){ for(int i=1;i<=n;i++) if(sccno[i]==star) ans++; printf("%d\n",ans); } else printf("0\n"); return 0;}

如果像我一样的萌(ju)新(ruo)有不太懂缩点的,我会在以后的文章中作为OI学习总结再次提到。

转载于:https://www.cnblogs.com/Neonen/p/9832502.html

你可能感兴趣的文章
局域网内手机访问电脑网站注意几点
查看>>
[Serializable]的应用--注册码的生成,加密和验证
查看>>
Linux操作系统 和 Windows操作系统 的区别
查看>>
Android-多线程AsyncTask
查看>>
LeetCode【709. 转换成小写字母】
查看>>
如何在Access2007中使用日期类型查询数据
查看>>
CF992E Nastya and King-Shamans(线段树二分+思维)
查看>>
第一个Java Web程序
查看>>
树状数组_一维
查看>>
如果没有按照正常的先装iis后装.net的顺序,可以使用此命令重新注册一下:
查看>>
linux install ftp server
查看>>
嵌入式软件设计第8次实验报告
查看>>
算法和数据结构(三)
查看>>
Ubuntu下的eclipse安装subclipse遇到没有javahl的问题...(2天解决了)
查看>>
alter database databasename set single_user with rollback IMMEDIATE 不成功问题
查看>>
WCF揭秘——使用AJAX+WCF服务进行页面开发
查看>>
【题解】青蛙的约会
查看>>
IO流
查看>>
mybatis调用存储过程,获取返回的游标
查看>>
设计模式之装饰模式(结构型)
查看>>