BZOJ 1123: [POI2008]BLO

来源:互联网 发布:java web项目开发案例 编辑:程序博客网 时间:2024/04/29 16:44

Byteotia城市有n个 towns m条双向roads. 每条 road 连接 两个不同的 towns ,没有重复的road. 所有towns连通。

删去某点后会出现点对不连通的情况,那么这个点一定是割点。我们用tarjan找出所有的割点,借助dfs树来统计答案,在dfs树上记录以每个点为根的子树大小,假如割点为P,儿子为V,则对答案的公贡献就是sz[v]*(n-1-sz[v]),还要统计p所在块的贡献。
Tips:删去P后P和所有点都不连通,最后答案+2*(n-1).

#include<iostream>#include<algorithm>#include<cstring>#include<cstdio>#include<vector>using namespace std;const int maxn=100000+10;int low[maxn],pre[maxn],n,m,dfs_clock;long long ans[maxn],cnt[maxn],sz[maxn];vector<int> g[maxn];void dfs(int p,int fa){  low[p]=pre[p]=++dfs_clock;sz[p]=1;  for(int i=0;i<g[p].size();i++)  {    int v=g[p][i];    if(!pre[v])    {      dfs(v,p);sz[p]+=sz[v];      low[p]=min(low[p],low[v]);      if(low[v]>=pre[p])      {        ans[p]+=sz[v]*(long long)(n-1-sz[v]);        cnt[p]+=sz[v];      }    }    else if(pre[v]<pre[p]&&v!=fa) low[p]=min(low[p],pre[v]);  }  ans[p]+=(long long)(n-1-cnt[p])*cnt[p];}int main(){  //freopen("1123.in","r",stdin);  //freopen("1123.out","w",stdout);  scanf("%d%d",&n,&m);  for(int i=1;i<=n;i++) ans[i]=2*n-2;  for(int i=1;i<=m;i++)  {    int x,y;scanf("%d%d",&x,&y);    g[x].push_back(y);    g[y].push_back(x);  }  for(int i=1;i<=n;i++) if(!pre[i]) dfs(i,-1);  for(int i=1;i<=n;i++)    printf("%lld\n",ans[i]);  return 0;}
0 0
原创粉丝点击