2020ICPC·Xiaomi Network Trial Game D-Router Mesh (seeking the number of connected blocks after deleting the cut point)

Link: https://ac.nowcoder.com/acm/contest/7501/D
Source: Niuke
 

Time limit: C/C++ 1 second, other languages ​​2 seconds
Space limit: C/C++ 262144K, other languages ​​524288K
64bit IO Format: %lld

Title description

In a Mesh networking system, there are nn_{}n​ MI Routers, where mm_{}m​ pairs of MI Routers are bidirectionally connected. In order to check the stability of the system, for each MI Router, we should determine the number of connected components after removing it and relative connections from the system. And then assess that if we should add more MI Routers into the system. Print the numbers of connected components in residual system after removing each MI Router.

Enter description:

The first line contains two integers n,m (1≤n,m≤3×105)n,m~(1\le n,m\le 3\times 10^5)n,m (1≤n,m≤3×105), denoting the number of MI Routers and bidirectional connections in the Mesh networking system.

Following mm_{}m​ lines each contains two integers u,v (1≤u<v≤n)u,v~(1 \le u < v \le n)u,v (1≤u<v≤n), denoting the uu_{}u​-th MI Router has a bidirectional connection with the vv_{}v​-th MI Router.

It's guaranteed that there are no duplicated connections in input.

Output description:

Print one line containing nn_{}n​ integers, where ii_{}i​-th integer denotes the number of connected components after removing ii_{}i​-th MI Router and relative connections.

Example 1

enter

4 2
1 2
1 3

Output

3 2 2 1

Description

After removing the 1st MI Router and relative connections, there are 33_{}3​ connected components: {2},{3},{4}\{2\}, \{3\}, \{4\}_{}{2},{3},{4}​.
After removing the 2nd MI Router and relative connections, there are 22_{}2​ connected components: {1,3},{4}\{1, 3\}, \{4\}_{}{1,3},{4}​.
After removing the 3rd MI Router and relative connections, there are 22_{}2​ connected components: {1,2},{4}\{1, 2\}, \{4\}_{}{1,2},{4}​.
After removing the 4th MI Router and relative connections, there is only 11_{}1​ connected component: {1,2,3}\{1, 2, 3\}_{}{1,2,3}​.

Title:

Give an undirected graph that is not necessarily connected, and ask how many connected blocks remain after deleting each point

Tarjan finds the cut point and the number of connected blocks remaining after deletion. Save a board

https://blog.csdn.net/qq547276542/article/details/47782369

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <vector>
#include <map>
using namespace std;
const int MAXN=300010,MAXM=600010;
//点的下标切记转换成由1~n
struct Edge{
   int to,next;
   bool cut;  //是否为桥的标记*******
}edge[MAXM];  //边数组
/*    遍历点u的临接边
    for(int i=head[u];i!=-1;i=edge[i].next)
    {   edge[i]      } //edge[i]即为边
*/
int head[MAXN],tot;
int Low[MAXN],DFN[MAXN],Stack[MAXN];
int Index,top;
bool Instack[MAXN];
bool cut[MAXN];    //是否为割点的标记*********
int add_block[MAXN];   //删除一个点后增加的连通块
int bridge;     //记录桥的个数*******
int n, m;

void init(){  //加边前先初始化
   memset(DFN,0,sizeof(DFN));
   memset(Instack,false,sizeof(Instack));
   memset(add_block,0,sizeof(add_block));
   memset(cut,false,sizeof(cut));
   memset(head,-1,sizeof(head));
   tot=Index=top=bridge=0;
}

void add_edge(int u,int v){  ///添加无向边,只需调用一次!!!!
    edge[tot].to=v;  edge[tot].next=head[u] ; edge[tot].cut=false;
    head[u]=tot++;
    edge[tot].to=u;  edge[tot].next=head[v] ; edge[tot].cut=false;
    head[v]=tot++;
}

void Tarjan(int u,int pre){
    int v;
    Low[u]=DFN[u]=++Index;
    Stack[top++]=u;
    Instack[u]=true;
    int son=0;
    for(int i=head[u];i!=-1;i=edge[i].next){
         v=edge[i].to;
         if(v==pre)continue;
         if(!DFN[v]){     //如果没有访问过v
            son++;
            Tarjan(v,u);
            if(Low[u]>Low[v])Low[u]=Low[v];
            //判断无向边(u,v)是否是桥
            if(Low[v]>DFN[u]){
                bridge++;
                edge[i].cut=true;
                edge[i^1].cut=true;
            }
            //判断u是否为割点
            if(u!=pre&&Low[v]>=DFN[u]){
                cut[u]=true;
                add_block[u]++;
            }
         }
         else if(Low[u]>DFN[v])
            Low[u]=DFN[v];
    }
    if(u==pre&&son>1)cut[u]=true;
    if(u==pre)add_block[u]=son-1;
    Instack[u]=false;
    top--;
}

void solve(int N){  //  寻找割顶和桥,N为题目中结点数
     for(int i=1;i<=N;i++)    //防止图不连通
     if(!DFN[i])Tarjan(i,i);     //对于每一个连通分量都调用一次
}

bool vis[MAXN];
void dfs(int u) {
    vis[u] = 1;
    for(int i = head[u]; ~i; i = edge[i].next)
        if(!vis[edge[i].to])
            dfs(edge[i].to);
}

int main() {
    scanf("%d%d", &n, &m);
    int u, v;
    init();
    for(int i = 1; i <= m; ++i) {
        scanf("%d%d", &u, &v);
        add_edge(u, v);
    }
    solve(n);
    memset(vis, 0, sizeof(vis));
    int all = 0;
    for(int i = 1; i <= n; ++i) {
        if(!vis[i]) {
            dfs(i);
            all++;
        }
    }
    for(int i = 1; i <= n; ++i) {
        if(i > 1) printf(" ");
        printf("%d", all + add_block[i]);
    }
    printf("\n");
    return 0;
}

 

Guess you like

Origin blog.csdn.net/weixin_43871207/article/details/109278199