• 【题解】2020-2021 SWERC I.Emails


    link

    题意

    给定(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;
    }
    
  • 相关阅读:
    我所理解的三次握手
    网络舆情——初步了解
    【转载】位运算的密码
    【转载】基础排序算法简介
    【原创】关于hashcode和equals的不同实现对HashMap和HashSet集合类的影响的探究
    【原创】Java移位运算
    【原创】MapReduce计数器
    【原创】Hadoop机架感知对性能调优的理解
    【原创】一个复制本地文件到Hadoop文件系统的实例
    【转载】JAVA IO 流的总结
  • 原文地址:https://www.cnblogs.com/bobh/p/15375087.html
Copyright © 2020-2023  润新知