poj 2186--Popular Cows
2014-10-29 21:16
351 查看
题意:农场有N个大牛,有些大牛喜欢另外一些大牛,问有多少个大牛被其它所有牛喜欢。
题解:
易知根据输入建立N点M条有向边的图。
假设有X个大牛被所有牛喜欢,说明这X个大牛内部也互相喜欢,也即这X个点组成了一个强连通分量,且其他所有牛有指向这个分量的边,但是这个分量不会有指向其它任何牛的边(因为若有着样的牛,它一定也被强连通分量的牛喜欢,然后根据传递性,这个牛也被其它不在强连通分量的牛喜欢,但是这个牛不在强连通分量内,推出矛盾)。
算法:
首先根据tarjan算法求出图中的各个强连通分量,求强连通分量不同于双连通分量,只针对于有向图,使用点堆栈记录路径。遍历完所有与u相连的树边以及后向边后计算出low[u]后才进行分量的判定。
对强连通分量进行缩点,并对缩点的出度进行统计,若出度为0的点只有一个,则输出此连通分量规模,反之说明没有被所有牛喜欢的牛存在。
题解:
易知根据输入建立N点M条有向边的图。
假设有X个大牛被所有牛喜欢,说明这X个大牛内部也互相喜欢,也即这X个点组成了一个强连通分量,且其他所有牛有指向这个分量的边,但是这个分量不会有指向其它任何牛的边(因为若有着样的牛,它一定也被强连通分量的牛喜欢,然后根据传递性,这个牛也被其它不在强连通分量的牛喜欢,但是这个牛不在强连通分量内,推出矛盾)。
算法:
首先根据tarjan算法求出图中的各个强连通分量,求强连通分量不同于双连通分量,只针对于有向图,使用点堆栈记录路径。遍历完所有与u相连的树边以及后向边后计算出low[u]后才进行分量的判定。
对强连通分量进行缩点,并对缩点的出度进行统计,若出度为0的点只有一个,则输出此连通分量规模,反之说明没有被所有牛喜欢的牛存在。
#include<iostream> #include<cstring> #include<cstdio> #include<queue> using namespace std; #define maxN 10005 class node { public: short x; node* next; node():x(),next(0){} }; class adjList { public: node* adj[maxN]; adjList() { memset(adj,0,sizeof(adj)); } void adjInsert(short a,short b) { node* newNode = new node; newNode->x = b; newNode->next = adj[a]; adj[a] = newNode; return ; } }; class solve { private: int N,M; adjList graph; short stackTop; short index; short sccNum; short DFN[maxN]; //DFS发现时间 short low[maxN]; //能通过树边或者后向边到达的最小发现时间 short pointStack[maxN]; //点堆栈 short SccIndex[maxN]; //记录每个点属于哪个强连通分量 char IsInStack[maxN]; short degree[maxN]; short popularNum; short popularIndex; public: solve(int n,int m):N(n),M(m),index(1),stackTop(0),sccNum(0),popularNum(0) { char IsPopular = false; memset(DFN,0,sizeof(DFN)); memset(IsInStack,0,sizeof(IsInStack)); memset(degree,0,sizeof(degree)); processIn(); tarjan(); generateGSCC(); for(int i = 0;i < sccNum;i++) { if(!degree[i]) //计算出度为0的缩点个数 { popularNum++; popularIndex = i; } } if(popularNum == 1) { printf("%d\n",calcNum(popularIndex)); } else { printf("0\n"); } } void processIn(); void tarjan(); void dfs(short u); void generateGSCC(); int calcNum(int id); }; int solve::calcNum(int id) //计算出度为0的强连通分量规模 { int num = 0; for(int i = 1;i <= N;i++) { if(SccIndex[i] == id) { num++; } } return num; } void solve::processIn() { int a,b; for(int i = 0;i < M;i++) { scanf("%d%d",&a,&b); graph.adjInsert(a,b); } return ; } void solve::tarjan() { for(short i = 1;i <= N;i++) { if(!DFN[i]) //图可能不连通,若不连通此处可以直接返回 { dfs(i); } } return ; } void solve::dfs(short u) { pointStack[++stackTop] = u; DFN[u] = low[u] = ++index; IsInStack[u] = true; for(node* tmpNode = graph.adj[u];tmpNode != NULL;tmpNode = tmpNode->next) { short v = tmpNode->x; if(!DFN[v]) //树边 { dfs(v); low[u] = min(low[u],low[v]); } else if(IsInStack[v]) //后向边 { low[u] = min(low[u],DFN[v]); } } if(low[u] == DFN[u]) { while(stackTop&&low[pointStack[stackTop]] >= low[u]) { IsInStack[pointStack[stackTop]] = false; SccIndex[pointStack[stackTop--]] = sccNum; } sccNum++; } return ; } void solve::generateGSCC() { short i,j; node* tmpNode; for(i = 1;i <= N;i++) { for(tmpNode = graph.adj[i];tmpNode != NULL;tmpNode = tmpNode->next) { j = tmpNode->x; if(SccIndex[i] != SccIndex[j]) //进行缩点统计缩点出度 { degree[SccIndex[i]]++; } } } return ; } int main() { int N,M; while(~scanf("%d%d",&N,&M)) { solve poj_2186(N,M); } return 0; }
相关文章推荐
- poj 2186 Popular Cows
- poj 2186 Popular Cows
- poj 2186 Popular Cows 强连通分量tarjan算法
- poj 2186 Popular Cows
- POJ-2186 Popular Cows (SCC 强连通分量)
- POJ-2186 Popular Cows 强连通分量
- POJ - 2186 Popular Cows(强连通分量+缩点)
- 【POJ 2186 Popular Cows】+ 强连通
- POJ 2186 Popular Cows 强连通分量(Kosaraju)
- POJ 2186 Popular Cows(强联通分量缩点+tarjan算法)
- Popular Cows poj 2186(强连通分量+缩点 )
- poj 2186 Popular Cows(强连通分量模板题,tarjan)
- Popular Cows POJ - 2186 (强连通分量)
- POJ 2186-Popular Cows:强连通分量问题
- poj 2186 Popular Cows(tarjan + 强连通分量 + 缩点)
- POJ 2186 Popular Cows(强连通分量分解)
- Popular Cows - POJ 2186 Tarjan
- POJ 2186 Popular Cows(强连通分量+缩点)
- POJ 2186 Popular Cows【Tarjan缩点+建缩点图】
- POJ 2186 -- Popular Cows【强连通分支 && Tarjan缩点】