UVA10765 题解

题目传送门

显然,在 tarjan 的时候,假设遇到一个 \(dfn[u]\le low[v]\) 的节点,那么我们删去这个节点后一定会多出一个连通块,比如这样:

UVA10765 题解

删去节点 \(5\) 后显然还剩下 \(3\) 个连通块,在这种情况下,我们看到节点 \(2,3\) 都满足上述条件,于是删去以后会多出来 \(2\) 个,加上原来的 \(1\) 个。

对于不是割点的,删去后一定还剩下一个。

于是我们就得出了以下结论

  • 对于割点:每满足有一个 \(dfn[u]\le low[v]\) 的节点,删去后的连通块就多一个。

  • 对于其他节点:删去后一定只剩一个。

于是我们又可以发现其实第二个结论根本没必要,不是割顶一定满足不了 \(dfn[u]\le low[v]\)。

最后因为要序号小的在前,我们直接用结构体存下来就好了。

Code:

#include<iostream>
#include<vector>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=1e4+5;
vector <int> G[maxn];
int dfn[maxn],low[maxn];
struct dat{
	int w,id;
	bool operator <(const dat& rhs)const{
		if(w>rhs.w)return true;
		if(w==rhs.w)return id<rhs.id;
		return false;
	}
}cnt[maxn];
int num;
void tarjan(int u,int pa){
	dfn[u]=low[u]=++num;
	int ch=0;
	for(int i=0;i<G[u].size();++i){
		int v=G[u][i];
		if(!dfn[v]){
			tarjan(v,u);
			low[u]=min(low[u],low[v]);
			if(dfn[u]<=low[v]){
				if(++ch>1||u!=1)cnt[u].w++;
			}
		}
		else if(v!=pa)low[u]=min(dfn[v],low[u]);
	}
}
int main(){
	int n,m;
	while(cin>>n>>m&&n&&m){
		int u,v;
		memset(dfn,0,sizeof(dfn));
		memset(cnt,0,sizeof(cnt));
		for(int i=0;i<=n;++i){
			G[i].clear();
			cnt[i].id=i;
		}
		while(cin>>u>>v&&u>=0&&v>=0){
			G[u].push_back(v);
			G[v].push_back(u);
		}
		tarjan(1,0);
		sort(cnt,cnt+n);
		for(int i=0;i<m;++i)
			cout<<cnt[i].id<<" "<<cnt[i].w+1<<endl;
		cout<<endl;
	}
	return 0;
}
上一篇:P5180-[模板]支配树


下一篇:[loj2049]网络