POJ 2186 Popular Cows 强连通分量 Kosaraju算法
2014-11-23 22:24
441 查看
题意:有N头牛,他们之间有M个关系(A,B),即A认为B是欢迎的,同时这种欢迎关系是传递的。现在要求出有多少牛被其他的所有牛认为是欢迎的。
思路:首先这是一个有向图。可以想到,对于一个强连通分量里的牛,每个牛都是被其他牛认为是欢迎的。这样,通过强连通缩点后,就变成了一个DAG。这样,能被其他牛认为是欢迎的,必然是拓扑排序的最后一个点。这样的话,我们就要用强连通分量的Kosaraju算法算法了。
注意:需要注意的一点是,最后我们还要判断其他所有的点能否到达最后一个点,否则就没有满足条件的牛。
代码如下:
思路:首先这是一个有向图。可以想到,对于一个强连通分量里的牛,每个牛都是被其他牛认为是欢迎的。这样,通过强连通缩点后,就变成了一个DAG。这样,能被其他牛认为是欢迎的,必然是拓扑排序的最后一个点。这样的话,我们就要用强连通分量的Kosaraju算法算法了。
注意:需要注意的一点是,最后我们还要判断其他所有的点能否到达最后一个点,否则就没有满足条件的牛。
代码如下:
#include <cstdio> #include <algorithm> #include <cstring> #include <vector> using namespace std; template<class T> inline bool read(T &n){ T x = 0, tmp = 1; char c = getchar(); while ((c < '0' || c > '9') && c != '-' && c != EOF) c = getchar(); if (c == EOF) return false; if (c == '-') c = getchar(), tmp = -1; while (c >= '0' && c <= '9') x *= 10, x += (c - '0'), c = getchar(); n = x*tmp; return true; } template <class T> inline void write(T n) { if (n < 0) { putchar('-'); n = -n; } int len = 0, data[20]; while (n) { data[len++] = n % 10; n /= 10; } if (!len) data[len++] = 0; while (len--) putchar(data[len] + 48); } #define MAX_N 10001 #define MAX_M 50001 int v; vector <int> g[MAX_N]; vector <int> rg[MAX_N]; vector <int> vs; bool used[MAX_M]; int cmp[MAX_M]; int n,m; int a[MAX_M]; int b[MAX_M]; void addedge(int from,int to) { g[from].push_back(to); rg[to].push_back(from); } void dfs(int v) { used[v] = true; for(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] = true; cmp[v] = k; for(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 i = 0 ; i < v ; ++i) if(!used[i]) dfs(i); memset(used,0,sizeof(used)); int k = 0; for(int i = vs.size() -1; i >= 0; i--) if(!used[vs[i]]) rdfs(vs[i],k++); return k; } void solve() { v= n; for(int i = 0 ; i <m; ++i) addedge(a[i]-1,b[i]-1); int nn = scc(); int u = 0 , num= 0; for(int i = 0 ; i < v ; ++i) if(cmp[i] == nn-1) { u = i; num++; } memset(used,0,sizeof(used)); rdfs(u,0); for(int i = 0 ; i < v; ++i) if(!used[i]) { num = 0; break; } printf("%d\n",num); } int main(void) { read(n),read(m); for(int i = 0; i <m ; ++i) read(a[i]),read(b[i]); solve(); return 0; }
相关文章推荐
- [ACM] POJ 2186 Popular Cows (强连通分量,Kosaraju算法知识整理)
- POJ 2186 Popular Cows (强连通分量)
- poj 2186 Popular Cows (强连通分量 tarjan)
- POJ 2186 Popular Cows【强连通分量】
- poj_2186 Popular Cows(强连通分量)
- POJ 2186 Popular Cows(强连通,kosaraju算法)
- POJ 2186 Popular Cows(强连通分量)
- POJ 2186 Popular Cows 强连通分量
- poj 2186 Popular Cows 【强连通分量】
- POJ 2186 Popular Cows 强连通分量 Kosaraju or tarjan
- POJ 2186 Popular Cows(强连通分量)
- poj 2186 Popular Cows(tarjan + 强连通分量 + 缩点)
- POJ 2186 Popular Cows (强连通分量)
- 【POJ 2186】Popular Cows(强连通分量_tarjan)
- POJ2186 Popular Cows 【强连通分量】+【Kosaraju】+【Tarjan】+【Garbow】
- 【poj 2186】Popular Cows(强连通分量)
- poj 2186 Popular Cows (强连通分量,缩点)
- POJ 2186 Popular Cows(强连通分量分解)
- poj 2186 Popular Cows 强连通分量
- POJ 2186 Popular Cows (强连通分量)