题意
给定(n)个人之间的关系图(无向图),一开始每个人的通讯录中有与他相邻的人的联系方式。在每一轮中,每个人都会将自己通讯录中所有人的联系方式发送给他当前通讯录中的所有人(注意不是一开始与他相邻的人)。求多少轮后所有都有所有其他人的联系方式。如果正确答案为(E),则你输出(E)或(E+1)都视为正确。
(2le nle 10^5,1le mle 10^5)
题解
易得在有限轮之后该过程一定停止,且两个人(u,v)在(lceil log_2(d(u,v)) ceil)轮后相互知晓对方,故(E=lceil log_2(Diam (G)) ceil)。由于最后允许和答案有一轮的容忍程度,我们可以不需要精确求出图直径的长度。我们从任意一点出发(BFS),设与其最远的点和它的距离为(D),由于
[Dle Diam(G)le 2D,
]
故
[log_2 Dle log_2 Diam(G)le 1+log_2 D,
]
所以
[log_2 Diam(G)le log_2 D+1le log_2 Diam(G)+1,
]
即(Ele log_2 D+1le E+1),于是我们输出(lceil log_2 D ceil+1)即可。
(Diam(G)le 2D)的证明
反证法,假若不然,则有(Diam(G)>2D)。不妨设(s,t)是直径(Diam(G))的两端点,即(d(s,t)=Diam(G)),由于(d(u,s)le D,d(t,u)le D),所以(s ightarrow u ightarrow t)这条路径的长度不大于(2D),这与(d(s,t)=Diam(G)>2D)矛盾,故(Diam(G)le 2D)。
#include <bits/stdc++.h>
#define cle(x) memset(x,0,sizeof(x))
using namespace std;
const int N=100005,M=200005;
typedef long long ll;
const ll INF=1ll<<55;
struct edge{int v,w,nt;}e[M];
int cnt=0,h[N];
void add(int u,int v,int w){
e[++cnt].v=v;e[cnt].nt=h[u];e[cnt].w=w;h[u]=cnt;
}
int n,m,k,tag[N],S[N],p=0,a[N],b[N],cs=0,p1=0,p2=0,c[N],P,p3;
ll ans,d[N];
struct node{
int u;ll x;
bool operator<(const node &b)const{
return x>b.x;
}
};
priority_queue<node> q;
int dij(int s){
while(!q.empty())q.pop();
for(int i=1;i<=n;i++)d[i]=INF;
d[s]=0;q.push(node{s,0});
while(!q.empty()){
node na=q.top();q.pop();
if(na.x!=d[na.u])continue;
for(int i=h[na.u];i;i=e[i].nt){
int v=e[i].v;
if(d[na.u]+e[i].w<d[v]){
d[v]=d[na.u]+e[i].w;
q.push((node){v,d[v]});
}
}
}
int res=0;
for(int i=1;i<=n;i++){
if(d[i]==INF){printf("-1");exit(0);}
res=max<int>(res,d[i]);
}
return res;
}
void f1(){
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++){
int x,y,z;scanf("%d%d",&x,&y);
add(x,y,1);add(y,x,1);
}
int res=dij(1);
int ans=(int)ceil(log2(res))+1;
printf("%d",ans);
}
int main(){
f1();
return 0;
}