LuoguP3469 [POI2008]BLO-Blockade
阿新 • • 發佈:2020-07-25
分析
對每個點的貢獻進行分析:如果這個點不是割點,那麼去掉這個點圖仍然聯通,減少的訪問僅為這個點和其他點之間的聯絡,也就是\(2*(n-1)\)。如果這個點是割點,那麼去除之後圖會變成多個聯通塊。設第\(i\)個聯通塊的大小為\(size_i\),易知聯通塊之間減少的聯絡是\(\Sigma_i\Sigma_j size_isize_j\)。對這個式子做變形,得到\(\Sigma_i size_i(n-size_i-1)\)。於是可以在tarjan的同時求出這個值。把所有貢獻加一起就好了。
程式碼
#include <bits/stdc++.h> using namespace std; namespace StandardIO { template<typename T>inline void read (T &x) { x=0;T f=1;char c=getchar(); for (; c<'0'||c>'9'; c=getchar()) if (c=='-') f=-1; for (; c>='0'&&c<='9'; c=getchar()) x=x*10+c-'0'; x*=f; } template<typename T>inline void write (T x) { if (x<0) putchar('-'),x=-x; if (x>=10) write(x/10); putchar(x%10+'0'); } } using namespace StandardIO; namespace Fate { #define int long long const int N=500500; int n,m; int cnt; int head[N]; struct node { int to,next; } edge[N<<1]; int index; int dfn[N],low[N],size[N],cut[N]; int ans[N]; inline void add (int a,int b) { edge[++cnt].to=b,edge[cnt].next=head[a],head[a]=cnt; } void tarjan (int now) { int tmp=0;size[now]=1,dfn[now]=low[now]=++index; for (register int i=head[now]; i; i=edge[i].next) { int to=edge[i].to; if (!dfn[to]) { tarjan(to); size[now]+=size[to]; low[now]=min(low[now],low[to]); if (dfn[now]<=low[to]) { ans[now]+=tmp*size[to]; tmp+=size[to]; } } else { low[now]=min(low[now],dfn[to]); } } ans[now]+=tmp*(n-tmp-1); } inline void Stay_Night () { read(n),read(m); for (register int i=1; i<=m; ++i) { int x,y; read(x),read(y); add(x,y),add(y,x); } tarjan(1); for (register int i=1; i<=n; ++i) { write((ans[i]+n-1)*2),putchar('\n'); } } #undef int } int main () { Fate::Stay_Night(); }