标签:ade cut type lse name 遍历 const 就是 cto
#include <cstring>
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
typedef long long ll;
const int N = 1000010, M =1000010;
inline int read()
{
int x=0,t=1;
char ch=getchar();
while(ch>‘9‘||ch<‘0‘)
{
if(ch==‘-‘)t=-1;
ch=getchar();
}
while(ch>=‘0‘&&ch<=‘9‘) x=x*10+ch-‘0‘,ch=getchar();
return x*t;
}
int n, m;
int h[N], e[M], ne[M], idx;
int dfn[N], low[N], timestamp;
int stk[N], top;
int dcc_cnt;
int size[N];
bool cut[N];
//特判根节点
int root;
ll ans[N];
void add(int a, int b)
{
e[idx] = b, ne[idx] = h[a], h[a] = idx ++ ;
}
void tarjan(int u)
{
dfn[u] = low[u] = ++ timestamp;
size[u]=1;
int sum1=0;
int cnt = 0;
//遍历邻边
for (int i = h[u]; ~i; i = ne[i])
{
int j = e[i];
//如果没被遍历过
if (!dfn[j])
{
tarjan(j);
size[u]+=size[j];
low[u] = min(low[u], low[j]);
if (dfn[u] <= low[j])
{
//当前分支到 除了这个分支外的点的 数量
ans[u]+=(ll)size[j]*(n-size[j]);
sum1+=size[j];
cnt ++ ;
if (u != root || cnt > 1)
cut[u] = true;
}
}
else
low[u] = min(low[u], dfn[j]);
}
//如果不是割点,那么就都还联通,少的就是当前点到其他所有,其他所有到当前点
if(cut[u]==0)
ans[u]=2*(n-1);
else
//n-sum1-1 是其他所有,不包括当前点
//sum1+1 是以这个点为根的子树,包括当前点
//也就是,子树中的所有的点(包括当前点) 到不了其他的点
//加上 其他店到不了当前点
ans[u]+=(ll)(n-sum1-1)*(sum1+1)+(n-1);
}
int main()
{
//初始化
idx = n = timestamp = top = dcc_cnt = 0;
n=read(),m=read();
memset(h, -1, sizeof h);
memset(dfn, 0, sizeof dfn);
memset(cut, 0, sizeof cut);
//读边
while (m -- )
{
int a=read(), b=read();
add(a, b), add(b, a);
}
//遍历所有点
for (root = 1; root <= n; root ++ )
if (!dfn[root])
tarjan(root);
for(int i=1; i<=n; i++)
cout<<ans[i]<<endl;
return 0;
}
luogu P3469 [POI2008]BLO-Blockade 割点
标签:ade cut type lse name 遍历 const 就是 cto
原文地址:https://www.cnblogs.com/QingyuYYYYY/p/12922601.html