自学内容网 自学内容网

P4630 [APIO2018] 铁人两项(圆方树模版)

*原题链接*

圆方树相关的东西小粉兔讲的太详细了!!(洛谷日报

在此贴出适合我体质的模版,至于讲解,咱肯定讲的没小粉兔好o(╥﹏╥)o。

圆方树模版:

void tarjan(int x){
dfn[x]=low[x]=++tim,stk[++top]=x;
for(int i=head[x];i;i=edge[i].nxt){
int y=edge[i].to;
if(!dfn[y]){
tarjan(y);
low[x]=min(low[x],low[y]);
if(low[y]==dfn[x]){
cnt++;int t;
do{
t=stk[top--],add(t,cnt),add(cnt,t);
}while(t!=y);//注意截止条件
add(x,cnt),add(cnt,x);//别忘了和x连边
}
}
else low[x]=min(low[x],dfn[y]);
}
}

整题代码:

#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=2e5+10;

int read(){
int x=0,f=1;char ch=getchar();
while(!isdigit(ch)){
if(ch=='-') f=-1;
ch=getchar();
}
while(isdigit(ch)) x=x*10+ch-'0',ch=getchar();
return x*f;
}

int n,m,head[N],tot,he[N],tot2,w[N],sz[N],ans,num,vis[N];
int dfn[N],low[N],tim,stk[N],top,cnt;
struct node{
int to,nxt;
}e[N*2],edge[N*2];
void add(int x,int y){
edge[++tot].to=y;
edge[tot].nxt=head[x];
head[x]=tot;
}
void ADD(int x,int y){
e[++tot2].to=y;
e[tot2].nxt=he[x];
he[x]=tot2;
}

void tarjan(int x){
dfn[x]=low[x]=++tim,stk[++top]=x,num++;
for(int i=he[x];i;i=e[i].nxt){
int y=e[i].to;
if(!dfn[y]){
tarjan(y);
low[x]=min(low[x],low[y]);
if(low[y]==dfn[x]){
cnt++;int t;
do{
w[cnt]++,t=stk[top--],add(t,cnt),add(cnt,t);
}while(t!=y);
add(x,cnt),add(cnt,x),w[cnt]++;
}
}
else low[x]=min(low[x],dfn[y]);
}
}

void dfs(int x){
vis[x]=1;sz[x]=(x<=n);
for(int i=head[x];i;i=edge[i].nxt){
int y=edge[i].to;
if(vis[y]) continue;
dfs(y);
ans+=2*sz[x]*sz[y]*w[x];
sz[x]+=sz[y];
}
ans+=2*sz[x]*(num-sz[x])*w[x];
}

signed main(){

n=read(),m=read();cnt=n;for(int i=1;i<=n;i++) w[i]=-1;
for(int i=1;i<=m;i++){int x=read(),y=read();ADD(x,y),ADD(y,x);}
for(int i=1;i<=n;i++){
if(!dfn[i]){memset(vis,0,sizeof(vis)),num=0,tarjan(i),dfs(i);}
}
cout<<ans<<endl;

return 0;
}


原文地址:https://blog.csdn.net/summ1ts/article/details/142469954

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!