HDU 6165-强连通分量+拓扑
Posted 水明
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HDU 6165-强连通分量+拓扑相关的知识,希望对你有一定的参考价值。
题意
给出一幅有向图,判定是否存在一对顶点互相不可达。
分析
在一个强连通分量里的点对是互相可达的,我们先求出强连通分量再缩点构建新图
然后我们对新图进行拓扑排序,当开始时或者删完一个点及它的关联边时,若入度为0的点多于1个,则这些点互相不可达
代码
#include <map> #include <set> #include <queue> #include <cmath> #include <ctime> #include <vector> #include <cstdio> #include <cstring> #include <cstdlib> #include <iostream> #include <algorithm> #define MAX 10007 #define MAXN 10007 #define MAXM 20007 #define INF 0x3f3f3f3f #define NINF 0xc0c0c0c0 #define MOD 1000000007 using namespace std; typedef long long LL; struct Edge{int to,next;}edge[MAXM]; int head[MAXN],tot; int Low[MAXN],DFN[MAXN],Stack[MAXN],Belong[MAXN];//Belong数组的值是1~scc int Index,top; int scc;//强连通分量的个数 bool Instack[MAXN]; int num[MAXN];//各个强连通分量包含点的个数,数组编号1~scc //num数组不一定需要,结合实际情况 void addEdge(int u,int v) { edge[tot].to=v; edge[tot].next=head[u]; head[u]=tot++; } void Tarjan(int u) { int v; Low[u]=DFN[u]=++Index; Stack[top++]=u; Instack[u]=true; for(int i=head[u];i!=-1;i=edge[i].next){ v=edge[i].to; if(!DFN[v]){ Tarjan(v); if(Low[u]>Low[v])Low[u]=Low[v]; } else if(Instack[v]&&Low[u]>DFN[v]) Low[u]=DFN[v]; } if(Low[u]==DFN[u]){ scc++; do{ v=Stack[--top]; Instack[v]=false; Belong[v]=scc; num[scc]++; }while(v!=u); }//printf("scc=%d\n",scc); } void solve(int N) { memset(DFN,0,sizeof DFN); memset(Instack,false,sizeof Instack); memset(num,0,sizeof num); Index=scc=top=0; for(int i=1;i<=N;i++) if(!DFN[i])Tarjan(i); } Edge edge1[MAXM]; int tot1,head1[MAXN],odeg1[MAXN],indegree[MAXN]; void addEdge1(int u,int v) { odeg1[u]++; indegree[v]++; edge1[tot1].to=v; edge1[tot1].next=head1[u]; head1[u]=tot1++; } void reduce(int N){ tot1=0; memset(head1,-1,sizeof head1); memset(odeg1,0,sizeof odeg1); memset(indegree,0,sizeof indegree); for(int u=1;u<=N;u++){ for(int k=head[u];k!=-1;k=edge[k].next){ int v=edge[k].to; if(Belong[u]!=Belong[v]){ addEdge1(Belong[u],Belong[v]); } } } } bool topo(int n){ priority_queue<int, vector<int>,greater<int> > Q; int ans[MAXN],iq=0; for(int i=1;i<=n;i++){ //printf("%d\n",indegree[i]); if(indegree[i]==0) Q.push(i); } // if(Q.size()!=1)return false;//printf("flag1\n"); while(!Q.empty()){//printf("sizeof q is %d\n",Q.size()); if(Q.size()!=1)return false; int qt=Q.top(); ans[iq++]=qt; Q.pop(); for(int k=head1[qt];k!=-1;k=edge1[k].next){ int t=edge1[k].to; indegree[t]--; if(indegree[t]==0) Q.push(t); } } return true; } void init() { tot=0; memset(head,-1,sizeof head); } int main(){ int cas,n,m,u,v; scanf("%d",&cas); while(cas--){ init(); scanf("%d%d",&n,&m); for(int i=1;i<=m;i++){ scanf("%d%d",&u,&v); addEdge(u,v); } solve(n); reduce(n); printf(topo(scc)?"I love you my love and our love save us!\n" :"Light my fire!\n"); } return 0; }
以上是关于HDU 6165-强连通分量+拓扑的主要内容,如果未能解决你的问题,请参考以下文章
HDU 3836 Equivalent Sets(强连通分量)
2017 Multi-University Training Contest - Team 9 1005&&HDU 6165 FFF at Valentine强联通缩点+拓扑排序((代