标签:dig size cst 一个 mes getchar count inline 缩点
题目:BZOJ1051、洛谷P2341。
题目大意:给你一张有向图,问有多少个点能从其他任意点到达。
解题思路:首先求强连通分量,缩点。
然后就变成有向无环图上的问题了。
这里有一个巧妙的思路:找出度为0的点。
由于是有向无环图,任意一个能从其他点到达的点出度一定是0,否则就会有环。
而这样的点最多有一个,如果有多个这样的点,它们两两之间已经不连通,已经不符合题意。
所以求各个点的出度,当只有一个出度为0的点(强连通分量)时,输出它原来包含的点的个数,否则输出0即可。
C++ Code:
#include<cstdio> #include<cctype> #include<cstring> #include<set> using namespace std; #define N 10005 int n,m,head[N],dfn[N],low[N],sta[N],ys[N],sz[N],top,idx,ltfl; bool vis[100005]; set<int>deg[N]; struct edge{ int from,to,nxt; }e[100005]; inline int readint(){ char c=getchar(); for(;!isdigit(c);c=getchar()); int d=0; for(;isdigit(c);c=getchar()) d=(d<<3)+(d<<1)+(c^‘0‘); return d; } void tarjan(int now){ vis[sta[++top]=now]=true; dfn[now]=low[now]=++idx; for(int i=head[now];i;i=e[i].nxt) if(!dfn[e[i].to]){ tarjan(e[i].to); if(low[now]>low[e[i].to]) low[now]=low[e[i].to]; }else if(vis[e[i].to]&&low[now]>dfn[e[i].to]) low[now]=dfn[e[i].to]; if(dfn[now]==low[now]){ ++ltfl; int k; do{ vis[k=sta[top--]]=false; ys[k]=ltfl; ++sz[ltfl]; }while(k!=now); } } int main(){ top=ltfl=0; memset(head,0,sizeof head); n=readint(),m=readint(); for(int i=1;i<=m;++i){ int x=readint(),y=readint(); e[i]=(edge){x,y,head[x]}; head[x]=i; } memset(dfn,0,sizeof dfn); memset(low,0,sizeof low); for(int i=1;i<=n;++i) if(!dfn[i]){ idx=0; memset(vis,0,sizeof vis); tarjan(i); } for(int i=1;i<=m;++i) if(ys[e[i].to]!=ys[e[i].from]&&!deg[ys[e[i].to]].count(ys[e[i].from])) deg[ys[e[i].from]].insert(ys[e[i].to]); int ans=0; bool b=false; for(int i=1;i<=ltfl;++i) if(!deg[i].size()){ if(b){ puts("0"); return 0; } ans=sz[i]; b=true; } printf("%d\n",ans); return 0; }
标签:dig size cst 一个 mes getchar count inline 缩点
原文地址:http://www.cnblogs.com/Mrsrz/p/7766004.html