UVA10765 题解

Posted all_WA

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了UVA10765 题解相关的知识,希望对你有一定的参考价值。

题目传送门

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

删去节点 \\(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;
}

以上是关于UVA10765 题解的主要内容,如果未能解决你的问题,请参考以下文章

UVA10765Doves and bombs (BCC求割点后联通块数量)

uva 10765 Doves and Bombs(割顶)

吃炸弹的鸽子UVA10765-双联通模板

题解Street Numbers [UVA138]

UVa 307 Sticks 题解

题解 UVa11727