zoukankan      html  css  js  c++  java
  • 【BZOJ-1123】BLO Tarjan 点双连通分量

    1123: [POI2008]BLO

    Time Limit: 10 Sec  Memory Limit: 162 MB
    Submit: 970  Solved: 408
    [Submit][Status][Discuss]

    Description

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

    Input

    输入n<=100000 m<=500000及m条边

    Output

    输出n个数,代表如果把第i个点去掉,将有多少对点不能互通。

    Sample Input

    5 5
    1 2
    2 3
    1 3
    3 4
    4 5

    Sample Output

    8
    8
    16
    14
    8

    HINT

    Source

    Solution

    题意叙述不清。

    题目大意:给定N个点M条边的无向图,问删除每个点后,对于有序数对(x,y)满足x,y互不连通的数对数。其中,被删掉的点也应被统计。

    这种和删点,联通有关的,可以考虑割点/点双联通分量。

    这个题也是,如果删除一个割点,那么答案个数就是裂成的几个块用乘法原理统计答案。如果删除一个非割点则可能会对其他点直接不影响。

    可以考虑在Tarjan的过程中求解,我们额外记录一个size表示分成的联通块的大小,然后我们在Tarjan的过程中统计答案即可

    Code

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #include<vector>
    using namespace std;
    #define LL long long
    inline int read()
    {
        int x=0,f=1; char ch=getchar();
        while (ch<'0' || ch>'9') {if (ch=='-') f=-1; ch=getchar();}
        while (ch>='0' && ch<='9') {x=x*10+ch-'0'; ch=getchar();}
        return x*f;
    }
    #define MAXN 100010
    #define MAXM 500010
    struct EdgeNode{int next,to;}edge[MAXM<<1];
    int head[MAXN],cnt=1;
    inline void AddEdge(int u,int v) {cnt++; edge[cnt].next=head[u]; head[u]=cnt; edge[cnt].to=v;}
    inline void InsertEdge(int u,int v) {AddEdge(u,v); AddEdge(v,u);}
    int N,M;
    vector<int>BCC[MAXN];
    #define Pa pair<int,int>
    Pa st[MAXM]; int top;
    int dfn[MAXN],low[MAXN],dfsn,son[MAXN],size[MAXN],cut[MAXN],bcc,belong[MAXN];
    LL sum[MAXN];
    inline void Tarjan(int now,int last)
    {
        dfn[now]=low[now]=++dfsn;  LL su=0; size[now]=1;
        for (int i=head[now]; i; i=edge[i].next)
            if (!dfn[edge[i].to])
                {
                    st[++top]=make_pair(now,edge[i].to); son[now]++;
                    Tarjan(edge[i].to,now); low[now]=min(low[now],low[edge[i].to]);
                    size[now]+=size[edge[i].to];
                    if (dfn[now]<=low[edge[i].to])
                        {
                            sum[now]+=su*size[edge[i].to]; su+=(LL)size[edge[i].to];
                            cut[now]=1; bcc++; BCC[bcc].clear(); int tnow=-1,tto=-1;
                            while (tnow!=now && tto!=edge[i].to)
                                {
                                    tnow=st[top].first,tto=st[top].second; top--;
                                    if (belong[tnow]!=bcc) BCC[bcc].push_back(tnow),belong[tnow]=bcc;
                                    if (belong[tto]!=bcc) BCC[bcc].push_back(tto),belong[tto]=bcc;
                                }
                        }
                }
            else if (dfn[edge[i].to]<dfn[now] && edge[i].to!=last)
                st[++top]=make_pair(now,edge[i].to),low[now]=min(low[now],dfn[edge[i].to]);
        if (last<0 && son[now]==1) cut[now]=0;
        sum[now]+=su*(N-su-1);
    }
    int main()
    {
        N=read(),M=read();
        for (int x,y,i=1; i<=M; i++) x=read(),y=read(),InsertEdge(x,y);
        for (int i=1; i<=N; i++) if (!dfn[i]) Tarjan(i,-1);
        for (int i=1; i<=N; i++) printf("%lld
    ",(LL)(sum[i]+N-1)*2);
        return 0;
    }
  • 相关阅读:
    Java基础教程:对象比较排序
    算法:深度优先搜索
    微信小程序开发:学习笔记[5]——JavaScript脚本
    微信小程序开发:学习笔记[4]——样式布局
    设计模式:学习笔记(8)——装饰器模式
    设计模式:学习笔记(7)——原型模式
    设计模式——单例模式解析
    玩转Android之数据库框架greenDAO3.0使用指南
    Android开发工具——Android Studio调试技巧
    VR开发的烦恼——范围限制
  • 原文地址:https://www.cnblogs.com/DaD3zZ-Beyonder/p/5904898.html
Copyright © 2011-2022 走看看