ACM: 图论题 poj 2186 强连通分量
2016-05-19 23:26
387 查看
Popular
Cows
Description
Every cow's dream is to become
the most popular cow in the herd. In a herd of N (1
<= N <= 10,000) cows, you are given
up to M (1 <= M <= 50,000) ordered
pairs of the form (A, B) that tell you that cow A thinks that cow B
is popular. Since popularity is transitive, if A thinks B is
popular and B thinks C is popular, then A will also think that C
is
popular, even if this is not explicitly specified by an ordered
pair in the input. Your task is to compute the number of cows that
are considered popular by every other cow.
Input
* Line 1: Two space-separated
integers, N and M
* Lines 2..1+M: Two space-separated numbers A and B, meaning that A
thinks B is popular.
Output
* Line 1: A single integer that
is the number of cows who are considered popular by every other
cow.
Sample Input
3 3
1 2
2 1
2 3
Sample Output
1
Hint
Cow 3 is the only cow of high
popularity.
题意: 给出每头牛u觉得牛v是受欢迎的, 欢迎是具有传递性的,
u->v, v->e ==>
u->e
现在计算出最受欢迎的牛的个数,
大家都认为才是最受欢迎, 否则为0
解题思路:
1. 一开始觉得题目很别扭, 最受欢迎并且是大家都认为的. 可仔细想想, 把全部支持
popularity牛看成一个集合,
集合内肯定有一条边指向popularity牛, 那么就可以发
现, 全部支持popularity的牛是一个强连通分量, 而popularity牛也是一个强连通分
量.
2.
一个有向图中, 如果存在至少两个孤立强连通分量, 那么题目无解.(全部认为才有解).
否则,
每个强连通分量必定是彼此有一条边相连, 那么肯定会出现一个强连通分量, 它
是最受欢迎的, 并且集合元素个数就是解.(孤立指: 无法连通)
3. 题目分析完毕, 剩下是求强连通分量, tarjan算法即可.
代码:
#include
<cstdio>
#include <iostream>
#include <cstring>
using namespace std;
#define MAX 50005
#define MAXSIZE 10005
struct node
{
int v;
int next;
}edges[MAX];
int n, m;
int first[MAX], num;
int stack[MAXSIZE], top, bcc[MAXSIZE], count;
int dfn[MAXSIZE], low[MAXSIZE];
bool vis[MAXSIZE], flag[MAXSIZE];
int temp[MAXSIZE];
inline int min(int a, int
b)
{
return a < b ? a : b;
}
inline void add(int u, int
v)
{
edges[num].v =v;
edges[num].next = first[u];
first[u] = num++;
}
void readGraph()
{
num = top = count = 0;
memset(first, -1, sizeof(first));
memset(vis, false, sizeof(vis));
memset(bcc, 0, sizeof(bcc));
memset(dfn, 0, sizeof(dfn));
memset(low, 0, sizeof(low));
memset(temp, 0, sizeof(temp));
memset(flag, true, sizeof(flag));
int u, v;
for(int i = 0; i < m; ++i)
{
scanf("%d %d",
&u, &v);
add(u, v);
}
}
void tarjan(int u, int
deep)
{
dfn[u] = low[u] = deep+1;
vis[u] = true;
stack[top++] = u;
for(int e = first[u]; e != -1; e =
edges[e].next)
{
int v = edges[e].v;
if( !low[v] )
{
tarjan(v,
deep+1);
low[u] =
min(low[u], low[v]);
}
else if( vis[v] )
low[u] =
min(low[u], dfn[v]);
}
if(dfn[u] ==
low[u])
{
count++;
int v;
do
{
v =
stack[--top];
vis[v] =
false;
bcc[v] =
count;
}while( v != u);
}
}
int solve()
{
int i;
int result = 0;
int number = 0;
for(i = 1; i <= n; ++i)
{
if( !low[i] )
tarjan(i, 1);
//i, deep
}
for(i = 1; i
<= n; ++i)
{
temp[ bcc[i] ]++;
for(int e = first[i]; e != -1;
e = edges[e].next)
{
if( bcc[i] !=
bcc[ edges[e].v ] )
flag[
bcc[i] ] = false;
}
}
for(i = 1; i
<= count; ++i)
{
if( flag[i] )
{
number++;
result =
temp[i];
}
}
if(number == 1) return result;
else return 0;
}
int main()
{
// freopen("input.txt", "r", stdin);
while(scanf("%d %d", &n,
&m) != EOF)
{
readGraph();
int result = solve();
printf("%d\n", result);
}
return 0;
}
Cows
Description
Every cow's dream is to become
the most popular cow in the herd. In a herd of N (1
<= N <= 10,000) cows, you are given
up to M (1 <= M <= 50,000) ordered
pairs of the form (A, B) that tell you that cow A thinks that cow B
is popular. Since popularity is transitive, if A thinks B is
popular and B thinks C is popular, then A will also think that C
is
popular, even if this is not explicitly specified by an ordered
pair in the input. Your task is to compute the number of cows that
are considered popular by every other cow.
Input
* Line 1: Two space-separated
integers, N and M
* Lines 2..1+M: Two space-separated numbers A and B, meaning that A
thinks B is popular.
Output
* Line 1: A single integer that
is the number of cows who are considered popular by every other
cow.
Sample Input
3 3
1 2
2 1
2 3
Sample Output
1
Hint
Cow 3 is the only cow of high
popularity.
题意: 给出每头牛u觉得牛v是受欢迎的, 欢迎是具有传递性的,
u->v, v->e ==>
u->e
现在计算出最受欢迎的牛的个数,
大家都认为才是最受欢迎, 否则为0
解题思路:
1. 一开始觉得题目很别扭, 最受欢迎并且是大家都认为的. 可仔细想想, 把全部支持
popularity牛看成一个集合,
集合内肯定有一条边指向popularity牛, 那么就可以发
现, 全部支持popularity的牛是一个强连通分量, 而popularity牛也是一个强连通分
量.
2.
一个有向图中, 如果存在至少两个孤立强连通分量, 那么题目无解.(全部认为才有解).
否则,
每个强连通分量必定是彼此有一条边相连, 那么肯定会出现一个强连通分量, 它
是最受欢迎的, 并且集合元素个数就是解.(孤立指: 无法连通)
3. 题目分析完毕, 剩下是求强连通分量, tarjan算法即可.
代码:
#include
<cstdio>
#include <iostream>
#include <cstring>
using namespace std;
#define MAX 50005
#define MAXSIZE 10005
struct node
{
int v;
int next;
}edges[MAX];
int n, m;
int first[MAX], num;
int stack[MAXSIZE], top, bcc[MAXSIZE], count;
int dfn[MAXSIZE], low[MAXSIZE];
bool vis[MAXSIZE], flag[MAXSIZE];
int temp[MAXSIZE];
inline int min(int a, int
b)
{
return a < b ? a : b;
}
inline void add(int u, int
v)
{
edges[num].v =v;
edges[num].next = first[u];
first[u] = num++;
}
void readGraph()
{
num = top = count = 0;
memset(first, -1, sizeof(first));
memset(vis, false, sizeof(vis));
memset(bcc, 0, sizeof(bcc));
memset(dfn, 0, sizeof(dfn));
memset(low, 0, sizeof(low));
memset(temp, 0, sizeof(temp));
memset(flag, true, sizeof(flag));
int u, v;
for(int i = 0; i < m; ++i)
{
scanf("%d %d",
&u, &v);
add(u, v);
}
}
void tarjan(int u, int
deep)
{
dfn[u] = low[u] = deep+1;
vis[u] = true;
stack[top++] = u;
for(int e = first[u]; e != -1; e =
edges[e].next)
{
int v = edges[e].v;
if( !low[v] )
{
tarjan(v,
deep+1);
low[u] =
min(low[u], low[v]);
}
else if( vis[v] )
low[u] =
min(low[u], dfn[v]);
}
if(dfn[u] ==
low[u])
{
count++;
int v;
do
{
v =
stack[--top];
vis[v] =
false;
bcc[v] =
count;
}while( v != u);
}
}
int solve()
{
int i;
int result = 0;
int number = 0;
for(i = 1; i <= n; ++i)
{
if( !low[i] )
tarjan(i, 1);
//i, deep
}
for(i = 1; i
<= n; ++i)
{
temp[ bcc[i] ]++;
for(int e = first[i]; e != -1;
e = edges[e].next)
{
if( bcc[i] !=
bcc[ edges[e].v ] )
flag[
bcc[i] ] = false;
}
}
for(i = 1; i
<= count; ++i)
{
if( flag[i] )
{
number++;
result =
temp[i];
}
}
if(number == 1) return result;
else return 0;
}
int main()
{
// freopen("input.txt", "r", stdin);
while(scanf("%d %d", &n,
&m) != EOF)
{
readGraph();
int result = solve();
printf("%d\n", result);
}
return 0;
}
相关文章推荐
- ACM: 博弈题 poj 1143 状态压缩
- 本周学习的代码(数构 深度 广度 优先遍历)
- [原创]关于设置linux中vim 显示行号
- ACM: 动态规划题 poj&nb…
- ACM: 图论题 poj 3…
- 兴趣学习: opencv 实现画图程序
- 兴趣学习: opencv -- 视频读写, 鼠…
- ACM: 动态规划题 poj 2923
- ACM: 动态规划题 poj&nb…
- ACM: 动态规划题 poj 3093 0-1背包
- ACM: 动态规划题 poj&nb…
- ipvsadm-2 DR模式及自动检测后端服务器状态
- ACM: 动态规划题 poj 3211 背包变…
- ACM: 动态规划题 poj&nb…
- ACM: 动态规划题 poj 3659
- ACM: 动态规划题 poj 1192 树形DP
- ACM: 动态规划题 poj&nb…
- ACM: 动态规划题 poj 3140
- ACM: 动态规划题 poj 2486
- ACM: 动态规划题 poj 1947