#98 pts Code:
#include<bits/stdc++.h>
#define ll long long
#define maxn 200050
#define maxm 600050
using namespace std;
int n,m,low[maxn],st[maxn],top,cnt2,siz[maxn],siz2[maxn],siztot;
int dfn[maxn],idx,root;
ll ans;
int read(){
int x=0,f=1;
char ch=getchar();
while (ch<'0'||ch>'9'){
if (ch=='-') f=-1;
ch=getchar();
}
while (ch>='0'&&ch<='9'){
x=(x<<1)+(x<<3)+(ch^48);
ch=getchar();
}
return x*f;
}
struct E{
int cnt,to[maxm],nxt[maxm],head[maxn];
void addedge(int a,int b){
to[cnt]=b;nxt[cnt]=head[a];head[a]=cnt++;
to[cnt]=a;nxt[cnt]=head[b];head[b]=cnt++;
}
}F,S;
void tarjang(int now,int f){
dfn[now]=++cnt2;low[now]=dfn[now];
st[++top]=now;siztot++;siz[now]=-1;
for (int i=F.head[now];i;i=F.nxt[i]){
int v=F.to[i];
if (i==(f^1)) continue;
if (!dfn[v]){
tarjang(v,i);
low[now]=min(low[now],low[v]);
if (low[v]>=dfn[now]){
int vv;idx++;
while (vv!=v){
vv=st[top--];
S.addedge(vv,idx+n);
siz[idx+n]++;
}
S.addedge(now,idx+n);
siz[idx+n]++;
}
}
else low[now]=min(low[now],dfn[v]);
}//build tree
}
void dfs(int now,int fa){
if (now<=n) siz2[now]++;
ll add=0;
for (int i=S.head[now];i;i=S.nxt[i]){
int v=S.to[i];
if (v==fa) continue;
dfs(v,now);
add+=(1ll*siz2[now]*siz2[v]);
siz2[now]+=siz2[v];
}
add+=(1ll*siz2[now]*(siztot-siz2[now]));
add<<=1;
ans+=(1ll*add*siz[now]);
}
void print(){
cout<<"||||";
for (int i=1;i<=n;i++)
cout<<low[i]<<" ";
cout<<endl;
}
int main(){
n=read();m=read();
F.cnt=2;S.cnt=2;
for (int i=1,u,v;i<=m;i++){
u=read();v=read();
F.addedge(u,v);
}
for (int i=1;i<=n;i++){
if (!dfn[i]){
root=i;
top=0;siztot=0;
tarjang(i,-1);
dfs(i,-1);
}
}
printf("%lld",ans);
return 0;
}
在tarjang算法中把f参数去掉就可以AC 为什么?不用保证不去走刚刚走过的边吗?