题目:
乱搞复杂度O(n^2)..
下面是黑字是蒟蒻的吐槽,蓝字是蒟蒻的口胡,仅供娱乐
其实一开始是想用记忆化搜索的..然后发现如果出现环的话,会访问到已经访问过的点且这个点的答案并没有完成更新,就会出错,所以就先用tarjan缩点重建图,这样就可以形成一个有向无环图,就避免了刚擦出错的情况
然后对于缩点后的图依旧是采用记忆化搜索去找它的连通数,对于一个已经找过联通数的点就不再去找直接累加。然后又会发现,还是太naive了,因为这样会重复,如题目中的图,2会直接加点3的答案即加3,同时2又会加上点5的答案,所以更新出来的点2除了它本身看到了4个点...想了想并没有什么好办法来判断重复,一开始又加了个vis,如果访问过就不再用它更新答案,但是又会遇到新的问题,即一个点被其他点访问过但同时又是这个点的答案,就更新不到它,答案就会少.....所以干脆就去掉了记忆化,但是并没有什么用,2依旧还会看到4个点...
最后,便开启了无脑暴搜模式,对每一个点做dfs,仅对当前这次dfs中访问过的点打上标记避免重复,每次找完一个点恢复所有点的标记以免查下一个点的时候更新不到答案
对于每个缩点后的点,它对其他点的贡献为它的size,它自己对答案的贡献为 size^2 + tt*size (其中tt表示它能到达的点的个数)
var
n,l,time,top,tt :longint;
ans :int64;
pre,other :array[0..8000010] of longint;
last,size :array[0..4010] of longint;
dfn,low,belong,z:array[0..2010] of longint;
vis,vis2 :array[0..4010] of boolean;
i,j :longint;
s :ansistring;
function min(a,b:longint):longint;
begin
if a<b then exit(a) else exit(b);
end;
procedure connect(x,y:longint);
begin
inc(l);
pre[l]:=last[x];
last[x]:=l;
other[l]:=y;
end;
procedure dfs(x:longint);
var
p,q,cur:longint;
begin
inc(time);
dfn[x]:=time;
low[x]:=time;
inc(top);
z[top]:=x;
vis[x]:=true;
//
q:=last[x];
while (q<>0) do
begin
p:=other[q];
if dfn[p]=0 then
begin
dfs(p);
low[x]:=min(low[x],low[p]);
end else
if vis[p] then low[x]:=min(low[x],dfn[p]);
q:=pre[q];
end;
//
if low[x]=dfn[x] then
begin
cur:=-1;
while cur<>x do
begin
cur:=z[top];
dec(top);
vis[cur]:=false;
belong[cur]:=n+x;
inc(size[n+x]);
end;
end;
end;
procedure dfs2(x:longint);
var
p,q:longint;
begin
vis2[x]:=true;
q:=last[x];
while (q<>0) do
begin
p:=other[q];
if not vis2[p] then
begin
inc(tt,size[p]);
dfs2(p);
end;
q:=pre[q];
end;
end;
procedure rebuild;
var
i,p,q:longint;
begin
for i:=1 to n do
begin
q:=last[i];
while (q<>0) do
begin
p:=other[q];
if belong[p]<>belong[i] then connect(belong[i],belong[p]);
q:=pre[q];
end;
end;
end;
begin
readln(n);
for i:=1 to n do
begin
readln(s);
for j:=1 to n do if s[j]='1' then connect(i,j);
end;
for i:=1 to n do if dfn[i]=0 then dfs(i);
rebuild;
for i:=1 to n do if not vis[belong[i]] then
begin
vis[belong[i]]:=true; tt:=0;
dfs2(belong[i]);
for j:=1 to n do vis2[belong[j]]:=false;
inc(ans,int64(size[belong[i]])*int64(size[belong[i]]));
inc(ans,int64(size[belong[i]])*int64(tt));
end;
writeln(ans);
end.
——by Eirlys