试题描述
|
求一个图删除一个点之后,联通块最多有多少。
|
输入
|
多组数据。第一行两个整数 P,C 表示点数和边数。
接下来 C 行每行两个整数 p1,p2,表示 p1 与 p2 有边连接,保证无重边。读入以 0 0 结束。 |
输出
|
输出若干行,表示每组数据的结果。
|
输入示例
|
3 3 0 1 0 2 2 1 4 2 0 1 2 3 3 1 1 0 0 0 |
输出示例
|
1 2 2 |
其他说明
|
数据范围与提示
1≤P≤10000,C≥0,0≤p1,p2<P |
割边的板子
不会的话点这里:https://www.cnblogs.com/WWHHTT/p/9745499.html
记录每一个点去掉之后会增加几个联通块
再和原来的个数相加
下面给出代码:
#include<iostream> #include<algorithm> #include<cstring> #include<string> #include<cmath> #include<cstdio> #include<cstdlib> using namespace std; inline int rd(){ int x=0,f=1; char ch=getchar(); for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-1; for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0'; return x*f; } inline void write(int x){ if(x<0) putchar('-'),x=-x; if(x>9) write(x/10); putchar(x%10+'0'); return ; } int n,m; int head[100006]; int nxt[200006],to[200006]; int total=0; void add(int x,int y){ total++; to[total]=y; nxt[total]=head[x]; head[x]=total; return ; } int dfn[100006],low[100006]; int tot=0; int num[100006]; void Tarjan(int x,int fa){ dfn[x]=low[x]=++tot; for(int e=head[x];e;e=nxt[e]){ if(!dfn[to[e]]){ Tarjan(to[e],x); low[x]=min(low[x],low[to[e]]); if(low[to[e]]>=dfn[x]) num[x]++; } else if(to[e]!=fa) low[x]=min(low[x],dfn[to[e]]); } return ; } int main(){ while(1){ memset(dfn,0,sizeof(dfn)); memset(head,0,sizeof(head)); memset(num,0,sizeof(num)); total=tot=0; n=rd(); m=rd(); if(!n&&!m) break; for(int i=1;i<=m;i++){ int x=rd(),y=rd(); add(x,y),add(y,x); } int cnt=0; int maxn=-999999; for(int i=0;i<n;i++){ if(!dfn[i]){ cnt++; Tarjan(i,-1); num[i]--; } } for(int i=0;i<n;i++){ maxn=max(maxn,num[i]); } write(cnt+maxn); puts(""); } return 0; }