社区讨论

暴力求调

P3304[SDOI2013] 直径参与者 1已保存回复 0

讨论操作

快速查看讨论及其快照的属性,并进行相关操作。

当前回复
0 条
当前快照
1 份
快照标识符
@lr229w7e
此快照首次捕获于
2024/01/06 20:48
2 年前
此快照最后确认于
2024/01/06 22:45
2 年前
查看原帖
CPP
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define oo 0x3ffffffffffff
const int N = 2e5+10;
int n;
int a,b,c;
int cnt;
int head[N];
int used[N];
int dis[N];
int pre[N];
int t[N];
int topos[N];
int num[N];
map<int,int>backpos[N];
struct node{
	int u,v,w,nex;
}edge[2*N];
struct dijsktra{
	int id,dis;
}now,then;
void add(int u,int v,int w){
	edge[++cnt].u=u;
	edge[cnt].v=v;
	edge[cnt].w=w;
	edge[cnt].nex=head[u];
	head[u]=cnt;
}
void clean(){
	for(int i=1;i<=n;i++){
		dis[i]=-oo;
		used[i]=0;
	}
}
void bfs(int x){
	queue<dijsktra>q;
	now.id=x;
	now.dis=0;
	dis[now.id]=0;
	q.push(now);
	while(!q.empty()){
		then=q.front();
		q.pop();
		if(used[then.id]) continue;
		used[then.id]=1;
		for(int i=head[then.id];i;i=edge[i].nex){
			int to=edge[i].v;
			if(used[to]) continue;
			dis[to]=dis[then.id]+edge[i].w;
			now.id=to;
			now.dis=dis[to];
			q.push(now);
		}
	}
}
void bfsbfs(int x,int mubiao){
	queue<int>q;
	q.push(x);
	pre[x]=-1;
	while(!q.empty()){
		int then=q.front();
		q.pop();
		if(used[then])  continue;
		if(then==mubiao){
			while(then!=-1){
				t[then]++;
				then=pre[then];//记录这一条直径走过的点 
			}
			for(int i=1;i<=n;i++) pre[i]=0;
			return;
		}
		used[then]=1;
		for(int i=head[then];i;i=edge[i].nex){
			int to=edge[i].v;
			if(used[to]) continue;
			pre[to]=then;
			q.push(to);
		}
	}
}
signed main(){
	cin>>n;
	for(int i=1;i<=n-1;i++){
		cin>>a>>b>>c;
		add(a,b,c);
		add(b,a,c);
	}
	bfs(1);
	int pd=-oo;
	for(int i=1;i<=n;i++){
		if(pd<dis[i]){
			pd=dis[i];
		}
	}
	int tot=0;
	for(int i=1;i<=n;i++){
		if(dis[i]==pd){
			topos[++tot]=i;
		}
	}
	clean();
	bfs(topos[1]);
	int kkk=-oo;
	for(int i=1;i<=n;i++){
		if(kkk<dis[i]){
			kkk=dis[i];
		}
	}
	cout<<kkk<<endl;
	for(int i=1;i<=tot;i++){
		clean();
		bfs(topos[i]);
		pd=-oo;
		for(int j=1;j<=n;j++){
			if(pd<dis[j]){
				pd=dis[j];
			}
		}
		for(int j=1;j<=n;j++){
			if(dis[j]==pd){
				backpos[topos[i]][++num[topos[i]]]=j;
			}
		}
	}
	clean();
	int number=0;
	for(int i=1;i<=tot;i++){
		for(int j=1;j<=num[topos[i]];j++){
			if(used[j]) continue;
			used[j]=1;
			number++;//直径的个数 
		}
	}
	int lastans=0;
	for(int i=1;i<=tot;i++){
		for(int j=1;j<=num[topos[i]];j++){
			clean();
			bfsbfs(topos[i],backpos[topos[i]][j]);
		}
	}
	for(int i=1;i<=n;i++){
		if(t[i]==number){
			lastans++;
		}
	}
	cout<<lastans-1;
	return 0;
}

整体思路: 求出每一条直径 求出每一条直径经过的点,并且标记 最后看哪些umber$次(直径的数量) 输出这些点的数量减1

回复

0 条回复,欢迎继续交流。

正在加载回复...