社区讨论
暴力求调
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 条回复,欢迎继续交流。
正在加载回复...