今天欧教让我们学习一下强连通分量的tarjan算法。
【题目名称】:受欢迎的牛
Description
每一头牛的愿望就是变成一头最受欢迎的牛。现在有N头牛,给你M对整数(A,B),表示牛A认为牛B受欢迎。这种关系是具有传递性的,如果A认为B受欢迎,B认为C受欢迎,那么牛A也认为牛C受欢迎。你的任务是求出有多少头牛被所有的牛认为是受欢迎的。
Input
第一行两个数N,M。
接下来M行,每行两个数A,B,意思是A认为B是受欢迎的(给出的信息有可能重复,即有可能出现多个A,B)
Output
一个数,即有多少头牛被所有的牛认为是受欢迎的。
Sample Input
3 3
1 2
2 1
2 3
Sample Output
1
【数据范围】
10%的数据N<=20, M<=50
30%的数据N<=1000,M<=20000
70%的数据N<=5000,M<=50000
100%的数据N<=10000,M<=50000
交了四次,WA完了。poj就是烦。。
和Wjj对拍了10分钟,没有错误。。。
这道题首先考虑没有环的情况。如果没有环,则可知,如果出度为0的点只有一个,那么所有的牛都认为他受欢迎。如果超过一个。则没有这样的牛。
所以可以考虑tarjan强连通缩点,如果出度为0的强连通块只有一个,那么就输出其中点的数量。其实tarjan并不难,只是一开始写忘了考虑多个连通块。
对于
这种情况,5不会被加入<5>这个强连通块。
关于tarjan算法的解释:http://www.byvoid.com/blog/scc-tarjan/
#include <iostream>
#include <bitset>
using std::cout;
using std::cin;
long n;
long tt = 0;
long t[10002];
long l[10002];
bool used[10002];
long top = 0;
long mm = 0;
long fl2[10002];
long fl[10002];
long stack[10002];
bool instack[10002];
long out[10002];
struct node
{
long index;
node* next;
};
node* dm[10002];
void insert(long a,long b)
{
node* tmp = new node;
tmp->index = b;
tmp->next = dm[a];
dm[a] = tmp;
}
void tarjan(long p)
{
t[p] = l[p] = ++tt;
stack[++top] = p;
instack[p] = true;
node* ths = dm[p];
while (ths)
{
long i = ths->index;
if (!used[i])
{
used[i] = true;
tarjan(i);
if (l[i]<l[p])l[p]=l[i];
}
else if(instack[i]&&t[i]<l[p])
l[p] = t[i];
ths = ths->next;
}
if (l[p]==t[p])
{
mm++;
while (stack[top]!=p)
{
fl[stack[top]]=mm;
fl2[mm]++;
instack[stack[top]] = false;
top--;
}
fl[p] = mm;//打错成fl[stack[p]]
fl2[mm]++;
instack[p] = false;
top--;
}
}
int main()
{
freopen("ans.out","w",stdout);
freopen("poj2186.in","r",stdin);
long tt;
cin >> n >> tt;
for (long i=1;i<tt+1;i++)
{
long a;long b;
cin >> a >> b;
insert(a,b);
}
for (long i=1;i<n+1;i++)
{//这里之前没有考虑多个连通块,所以错了
if (!used[i])
{
top = 0;
tarjan(i);
used[i] = true;
}
}
for (long i=1;i<n+1;i++)
{
node* ths = dm[i];
while (ths)
{
long j = ths->index;
if (fl[i]!=fl[j])
{
out[fl[i]]++;
}
ths = ths->next;
}
}
long cnt = 0;
long k = 0;
for (long i=1;i<mm+1;i++)
{
if (out[i]==0)
{
cnt ++;
if (cnt>1){cout<<0;return 0;}
k = i;
}
}
cout << fl2[k];
return 0;
}