bzoj1123 [POI2008]BLO——求割点子树相乘
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1123
思路倒是有的,不就是个乘法原理吗,可是不会写...代码能力...
写了一堆麻麻烦烦乱七八糟的东西写不下去了,去看TJ...
原来是在 tarjan 里面就顺便算出来了啊!真是精妙!这就是构建出了一个 dfs 搜索树了呢;
码力还需多多提升...
代码如下:
#include<iostream> #include<cstdio> #include<cstring> using namespace std; typedef long long ll; int const maxn=1e5+5,maxm=5e5+5; int n,m,hd[maxn],ct,siz[maxn],dfn[maxn],low[maxn],tim; ll ans[maxn]; struct N{ int to,nxt; N(int t=0,int n=0):to(t),nxt(n) {} }ed[maxm<<1],edge[maxm<<1]; void add(int x,int y){ed[++ct]=N(y,hd[x]); hd[x]=ct;} void tarjan(int x,int f) { dfn[x]=low[x]=++tim; ll t=0; siz[x]=1;//注意t是ll,否则下面算给ans时爆int for(int i=hd[x],u;i;i=ed[i].nxt) { if((u=ed[i].to)==f)continue; if(!dfn[u]) { tarjan(u,x); siz[x]+=siz[u]; low[x]=min(low[x],low[u]); if(low[u]>=dfn[x])ans[x]+=siz[u]*t,t+=siz[u];//t是割点的子树大小 } else low[x]=min(low[x],dfn[u]); } ans[x]+=t*(n-t-1); } int main() { scanf("%d%d",&n,&m); for(int i=1,x,y;i<=m;i++) { scanf("%d%d",&x,&y); add(x,y); add(y,x); } tarjan(1,0); for(int i=1;i<=n;i++)printf("%lld\n",(ans[i]+n-1)*2); return 0; }