BZOJ1123-BLO-Strong Connected Component Cutting Point+Count

[Title Description]

The city of Byteotia has n towns with m bidirectional roads. Each road connects two different towns without duplicate roads. All towns are connected.

Input

Enter n<=100000 m<=500000 and m edges

Output

The number of output n represents how many peers will not be able to communicate if the ith point is removed.

Sample Input

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

Sample Output

8
8
16
14
8

[Title Analysis]
The Title asks how many city pairs cannot be connected after deleting each point.
It is easy to associate strong connected component cutting points, which will surely result in many city pairs that are not connected, rather than cutting points which have no other disconnections besides themselves.(If you look closely at the example, you can see that you and other cities are included.)
But the question is how many cities are there for each cut point?
First, there must be no connectivity between different subtrees at the cut point
Secondly, the subtree of the cut point cannot be connected to any other point except the cut point
Finally: each deleted point cannot be connected to another point
It is important to note that each pair of points is calculated twice (which is also the result of the study sample)
The last simple one is (n-1)*2 (we won't talk about multiplying by 2 in any of the subsequent discussions, and finally multiplying by 2 is all that matters)
Secondly, if we only need to count how many points TMP are in all the subtrees of each cut point, then (n-1-tmp)*tmp is the answer
Focus on what to do first.Let's think about how to count the nodes of a subtree at each cut point. It must be searching for a subtree and backtracing the number of nodes of each subtree, then adding them up.For the current subtree (number of nodes num[v]), he and all the previous subtree nodes (number of nodes tmp=num[v1]+num[v2]+...+num[vi-1]) is not connected, so let's multiply the answer by num[v] and the sum of the preceding subtree nodes, then update the subtree nodes and just fine (see the code Trajan function section for more details)
[AC Code]

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<iostream>
#include<cmath>
#include<climits>
#include<queue>
#include<vector>
#include<set>
#include<map>
using namespace std;

typedef long long ll;
const int INF=0x3f3f3f3f;
const int MAXN=1e5+5;
const int MAXM=5e5+5;
struct node
{
    int v,next;
}Edge[MAXM<<1];
int head[MAXN],tot;
int DFN[MAXN],LOW[MAXN];
//bool cnt[MAXN];
int vis[MAXN],Time;
ll ans[MAXN],n,m;
ll num[MAXN];

void init()
{
    memset(head,0,sizeof(head));
    tot=0;
    memset(vis,0,sizeof(vis));
    Time=0;
    //memset(cnt,0,sizeof(cnt));
    memset(ans,0,sizeof(ans));
    memset(num,0,sizeof(num));
}

void AddEdge(int u,int v)
{
    tot++;
    Edge[tot].v=v; Edge[tot].next=head[u];
    head[u]=tot;
}

void read()
{
    int u,v;
    for(int i=0;i<m;i++)
    {
        scanf("%d%d",&u,&v);
        AddEdge(u,v); AddEdge(v,u);
    }
}

void Trajan(int x,int fa)
{
    int v; ll tmp=0;
    int son=0;
    DFN[x]=LOW[x]=++Time;
    vis[x]=1; num[x]=1;
    for(int i=head[x];i;i=Edge[i].next)
    {
        v=Edge[i].v;
        if(vis[v]==0)
        {
            Trajan(v,x);
            num[x]+=num[v];
            son++;
            LOW[x]=min(LOW[x],LOW[v]);
            //if(x==root &&son>1 || x!=root && LOW[v]>=DFN[x])
            if(LOW[v]>=DFN[x])  //There is no need to determine if the root node is a root node, because if the root node has only one subtree, tmp is 0, ans[x] is 0, and if more than one subtree is a cut point, it is calculated directly.
            {
                ans[x]+=tmp*num[v];
                tmp+=num[v];
                //cnt[x]=true;
            }
        }
        else if(vis[v]==1)
        {
            LOW[x]=min(LOW[x],DFN[v]);
        }
    }
    vis[x]==2;
    ans[x]+=tmp*(n-tmp-1);
}

void solve()
{
    for(int i=1;i<=n;i++)
    {
        if(!vis[i])
        {
            Trajan(i,i);
        }
    }
}

void print()
{
    for(int i=1;i<=n;i++)
    {
        printf("%lld\n",2ll*(ans[i]+n-1));
    }
}

int main()
{
    while(~scanf("%lld%lld",&n,&m))
    {
        init();
        read();
        solve();
        print();
    }

    return 0;
}

Added by quiphics on Mon, 19 Aug 2019 05:19:55 +0300