bzoj 1123 [POI2008]BLO——点双连通分量

题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1123

点双连通分量缩点,然后各种各样。

结果不会写了。比如新连边、记录一个点是割点缩成的点还是一块缩成的点什么的。

然后去学习了TJ。其实根本不用把缩点后的图真的建出来嘛!而且人家写得好好!唉,代码能力?

#include<iostream>
#include<cstdio>
#include<cstring>
#define ll long long
using namespace std;
const int N=1e5+5,M=5e5+5;
int n,m,hd[N],xnt,siz[N],dfn[N],low[N],tim;
ll ans[N];
struct Ed{
  int nxt,to;Ed(int n=0,int t=0):nxt(n),to(t) {}
}ed[M<<1];
void add(int x,int y)
{
  ed[++xnt]=Ed(hd[x],y);hd[x]=xnt;
  ed[++xnt]=Ed(hd[y],x);hd[y]=xnt;
}
void tarjan(int cr)
{
  dfn[cr]=low[cr]=++tim;siz[cr]=1;
  ll t=0;
  for(int i=hd[cr],v;i;i=ed[i].nxt)
    if(!dfn[v=ed[i].to])
      {
    tarjan(v);
    low[cr]=min(low[cr],low[v]);siz[cr]+=siz[v];
    if(low[v]>=dfn[cr])
      {
        ans[cr]+=t*siz[v];t+=siz[v];
      }
      }
    else low[cr]=min(low[cr],dfn[v]);
  ans[cr]+=t*(n-t-1);
}
int main()
{
  scanf("%d%d",&n,&m);int x,y;
  for(int i=1;i<=m;i++)
    {
      scanf("%d%d",&x,&y);add(x,y);
    }
  tarjan(1);
  for(int i=1;i<=n;i++)
    printf("%lld\n",(ans[i]+n-1)<<1);
  return 0;
}

 

posted on 2018-07-10 21:18  Narh  阅读(140)  评论(0编辑  收藏  举报

导航