您的位置:首页 > 其它

tarjan题目(2)爱在心中

2015-07-15 12:25 288 查看
【题目描述】:

“每个人都拥有一个梦,即使彼此不相同,能够与你分享,无论失败成功都会感动。爱因为在心中,平凡而不平庸,世界就像迷宫,却又让我们此刻相逢Our Home。”

在爱的国度里有N个人,在他们的心中都有着一个爱的名单,上面记载着他所爱的人(不会出现自爱的情况)。爱是具有传递性的,即如果A爱B,B爱C,则A也爱C。

如果有这样一部分人,他们彼此都相爱,则他们就超越了一切的限制,用集体的爱化身成为一个爱心天使。

现在,我们想知道在这个爱的国度里会出现多少爱心天使。而且,如果某个爱心天使被其他所有人或爱心天使所爱则请输出这个爱心天使是由哪些人构成的,否则输出-1。

【输入格式】:

第1行,两个数N、M,代表爱的国度里有N个人,爱的关系有M条。

第2到第M+1行,每行两个数A、B,代表A爱B。

【输出格式】:

第1行,一个数,代表爱的国度里有多少爱心天使。

第2行,如果某个爱心天使被其他所有人和爱心天使所爱则请输出这个爱心天使是由哪些人构成的(从小到大排序),否则输出-1。

【输入样例】:

样例输入1:

6 7

1 2

2 3

3 2

4 2

4 5

5 6

6 4

样例输入2:

3 3

1 2

2 1

2 3

【输出样例】:

样例输出1:

2

2 3

样例输出2:

1

-1

分析:

先缩点,用tarjan算法
再输出强连通分量个数(在这里强连通分量中1个以上才算强连通分量)
为了找出被所有人爱的一个集合
算出每个点的出度,出度为0的点才有可能被所有人爱
但是出度为0的点不能多于1个,如果多于一个则证明这是多棵树
也不能是一个点,因为他不是一个爱心天使

代码:
var

low,dfn,st,c,k,o,oo,k1:array [1..1000] of integer;

a:array [1..1000,1..1000] of integer;

b:array [1..1000,1..1000] of boolean;

f,v,boo:array [1..1000] of boolean;

bb:array [1..1000,1..2] of longint;

i,j,m,n,tot,x,y,d,t,ans,p:longint;

function min(x,y:longint):longint;

begin

if x>y then

exit(y);

exit(x);

end;

function pp:longint;

begin

f[st[t]]:=false;

dec(t);

exit(st[t+1]);

end;

procedure targan(x:longint);

var

i:longint;

begin

inc(d);

dfn[x]:=d;

low[x]:=d;

inc(t);

st[t]:=x;

f[x]:=true;

for i:=1 to c[x] do

begin

if not v[a[x,i]] then

begin

v[a[x,i]]:=true;

targan(a[x,i]);

low[x]:=min(low[x],low[a[x,i]]);

end else

begin

if f[a[x,i]] then

low[x]:=min(low[x],dfn[a[x,i]]);

end;

end;

if dfn[x]=low[x] then

begin

inc(p);

repeat

inc(o[p]);

y:=pp;

oo[y]:=p;

b[p,y]:=true;

until x=y;

if o[p]>1 then

inc(ans);

end;

end;

begin

readln(n,m);

for i:=1 to m do

begin

readln(x,y);

inc(c[x]);

inc(k1[y]);

a[x,c[x]]:=y;

bb[i,1]:=x;

bb[i,2]:=y;

end;

for i:=1 to n do

if not v[i] then

begin

v[i]:=true;

targan(i);

end;

writeln(ans);

for i:=1 to m do

begin

if (oo[bb[i,1]]<>oo[bb[i,2]]) then

boo[oo[bb[i,1]]]:=true;

end;

for i:=1 to p do

begin

if not boo[i] and (o[i]>1) then

begin

x:=i;

inc(tot);

end;

end;

if tot<>1 then

writeln('-1') else

for i:=1 to n do

if b[x,i] then

write(i,' ');

writeln;

end.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: