POJ 2186 强联通分量

时间:2023-03-09 07:51:16
POJ 2186 强联通分量

点击打开链接

题意:牛A喜欢牛B,若牛B喜欢牛C,则牛A喜欢牛C,问最后多少牛被其它全部牛喜欢

思路:用强联通分量进行缩点,最后形成的图是有向无环图DAG。而拓扑序的值为DAG的长度,则加一,可是最后我们要推断一下这些牛是不是被全部牛喜欢,由于等于DAG长度的全部点肯定是一个强联通分量,因此它们能够相互喜欢,我们用当中一仅仅牛推断即可了,推断时就用反向边推断这个牛能不能到达其它的牛即可了

#include <vector>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
const int inf=0x3f3f3f3f;
const int maxn=10010;
int V;
vector<int>G[maxn];
vector<int>rG[maxn];
vector<int>vs;
bool used[maxn];
int cmp[maxn];
void add_edge(int from,int to){
G[from].push_back(to);
rG[to].push_back(from);
}
void dfs(int v){
used[v]=1;
for(unsigned int i=0;i<G[v].size();i++){
if(!used[G[v][i]]) dfs(G[v][i]);
}
vs.push_back(v);
}
void rdfs(int v,int k){
used[v]=1;
cmp[v]=k;
for(unsigned int i=0;i<rG[v].size();i++){
if(!used[rG[v][i]]) rdfs(rG[v][i],k);
}
}
int scc(){
memset(used,0,sizeof(used));
vs.clear();
for(int v=0;v<V;v++){
if(!used[v]) dfs(v);
}
memset(used,0,sizeof(used));
int sum=0;
for(int i=vs.size()-1;i>=0;i--){
if(!used[vs[i]]) rdfs(vs[i],sum++);
}
return sum;
}
int main(){
int m;
while(scanf("%d%d",&V,&m)!=-1){
for(int i=0;i<maxn;i++) G[i].clear();
for(int j=0;j<maxn;j++) rG[j].clear();
int a,b;
for(int i=0;i<m;i++){
scanf("%d%d",&a,&b);
add_edge(a-1,b-1);
}
int t=scc(),ans=0,pos;
for(int i=0;i<V;i++){
if(cmp[i]==t-1){
ans++;
pos=i;
}
}
memset(used,0,sizeof(used));
rdfs(pos,0);
for(int i=0;i<V;i++){
if(used[i]==0){
ans=0;break;
}
}
printf("%d\n",ans);
}
return 0;
}