1 条题解

  • 0
    @ 2022-9-5 15:02:09
    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int N=1005;
    const int M=1e7+5;
    int Head[N],vet[N<<1],Next[N<<1];
    int p[N],x[N],y[N],fa[N],f[N],g[N],deg[N],pos[N],vis[N],siz[N],dis[N];
    ll vec[M],U[M],D[M];
    int L,tp,tq,edgenum,len,res;
    int Find(int u){ return fa[u]==u?u:fa[u]=Find(fa[u]); }
    void gen1(){  //第一种生成方法
    	for (int i=1; i<=1000; i++) p[i]=i;
    	random_shuffle(p+1,p+1+1000);
    	for (int i=2; i<=1000; i++) x[i-1]=p[rand()%(i-1)+1],y[i-1]=p[i];
    }
    void gen2(){  //第二种生成方法
    	for (int i=1; i<=1000; i++) p[i]=i;
    	random_shuffle(p+1,p+1+1000);
    	for (int i=2; i<=1000; i++) x[i-1]=p[i/2+rand()%(i-i/2)],y[i-1]=p[i];
    }
    void gen3(){  //第三种生成方法
    	for (int i=1; i<=1000; i++) fa[i]=i;
    	int cnt=0;
    	while (cnt<999){
    		int u=rand()%1000+1,v=rand()%1000+1;
    		if (Find(u)!=Find(v)){
    			cnt++; x[cnt]=u,y[cnt]=v;
    			fa[Find(u)]=Find(v);
    		}
    	}
    }
    void gen4(){  //第四种生成方法,随机prufer序列
    	for (int i=1; i<=998; i++) p[i]=rand()%1000+1;
    	set<int> s;
    	memset(vis,0,sizeof(vis));
    	for (int i=1; i<=998; i++) vis[p[i]]++;
    	for (int i=1; i<=1000; i++)
    		if (!vis[i]) s.insert(i);
    	for (int i=1; i<=998; i++){
    		int t=*s.begin();
    		x[i]=t,y[i]=p[i];
    		s.erase(t); vis[p[i]]--;
    		if (!vis[p[i]]) s.insert(p[i]);
    	}
    	int t=*s.begin();
    	s.erase(t);
    	x[999]=t,y[999]=*s.begin();
    }
    void gen(int t){
    	if (t==1) gen1();
    	if (t==2) gen2();
    	if (t==3) gen3();
    	if (t==4) gen4();
    }
    void dfs(int u, int F){
    	f[u]=1,g[u]=0;
    	for (int e=Head[u]; e; e=Next[e]){
    		int v=vet[e];
    		if (v==F) continue;
    		dfs(v,u);
    		if (f[v]+1>f[u]) g[u]=f[u],f[u]=f[v]+1;
    		else if (f[v]+1>g[u]) g[u]=f[v]+1;
    	}
    }
    void solve1(){
    	int ans=0; dfs(1,0);
    	for (int i=1; i<=1000; i++) ans=max(ans,f[i]+g[i]);
    	vec[++len]=ans;
    }
    void solve2(){
    	int ans=0;
    	for (int i=1; i<=1000; i++) ans+=(deg[i]==2);
    	vec[++len]=ans;
    }
    void solve10(){
    	int ans=0; dfs(1,0);
    	for (int i=1; i<=1000; i++) ans+=f[i]+g[i];
    	vec[++len]=ans;
    }
    void solve14(){
    	int ans=0; dfs(1,0);
    	for (int i=1; i<=1000; i++) ans+=f[i]*f[i]+g[i]*g[i];
    	vec[++len]=ans/50;
    }
    void solve3(){
    	int ans=0;
    	for (int i=1; i<=1000; i++) ans+=deg[i]*deg[i];
    	vec[++len]=ans;
    }
    void solve4(){
    	ll ans=0,sum=0;
    	for (int i=1; i<=1000; i++) sum+=deg[i];
    	for (int i=1; i<=1000; i++) ans+=1ll*(1000*deg[i]-sum)*(1000*deg[i]-sum);
    	vec[++len]=ans/100000;
    }
    void dfs1(int u, int f){
    	siz[u]=1; int mx=0;
    	for (int e=Head[u]; e; e=Next[e]){
    		int v=vet[e];
    		if (v==f) continue;
    		dfs1(v,u);
    		siz[u]+=siz[v];
    		mx=max(mx,siz[v]);
    	}
    	mx=max(mx,1000-siz[u]);
    	if (mx<res) res=mx;
    }
    int dfs2(int u, int f){
    	siz[u]=1; int mx=0,sum=0;
    	for (int e=Head[u]; e; e=Next[e]){
    		int v=vet[e];
    		if (v==f) continue;
    		sum+=dfs2(v,u);
    		siz[u]+=siz[v];
    		mx=max(mx,siz[v]);
    	}
    	mx=max(mx,1000-siz[u]);
    	return sum+mx;
    }
    void solve5(){
    	dfs1(1,0); int ans=0;
    	for (int i=1; i<=1000; i++) ans+=siz[i];
    	vec[++len]=ans;
    }
    void solve6(){
    	dfs1(1,0); int ans=0;
    	for (int i=1; i<=1000; i++) ans+=siz[i]*siz[i];
    	vec[++len]=ans;
    }
    void solve7(){
    	dfs1(1,0);
    	ll ans=0,sum=0;
    	for (int i=1; i<=1000; i++) sum+=siz[i];
    	for (int i=1; i<=1000; i++) ans+=1ll*(1000*siz[i]-sum)*(1000*siz[i]-sum);
    	vec[++len]=ans/100000;
    }
    void solve8(){ res=1e9; dfs1(1,0); vec[++len]=res; }
    void solve9(){ vec[++len]=dfs2(1,0); }
    double dfs3(int u, int f){
    	siz[u]=1; double sum=0;
    	for (int e=Head[u]; e; e=Next[e]){
    		int v=vet[e];
    		if (v==f) continue;
    		sum+=dfs3(v,u);
    		siz[u]+=siz[v];
    	}
    	sum+=log2(siz[u])+log2(1001-siz[u]);
    	return sum;
    }
    void solve11(){ vec[++len]=dfs3(1,0); }
    void solve12(){
    	queue<int> que; int ans=0;
    	for (int i=1; i<=1000; i++)
    		if (deg[i]==1) que.push(i),dis[i]=1;
    		else dis[i]=1e9;
    	while (!que.empty()){
    		int u=que.front(); que.pop();
    		for (int e=Head[u]; e; e=Next[e]){
    			int v=vet[e];
    			if (dis[v]!=1e9) continue;
    			deg[v]--;
    			if (deg[v]==1) que.push(v),dis[v]=dis[u]+1;
    		}
    		ans+=dis[u]*dis[u];
    	}
    	vec[++len]=ans;
    }
    void solve13(){
    	int ans=0;
    	for (int i=1; i<=1000; i++) ans+=(deg[i]==1);
    	for (int i=1; i<=1000; i++) ans-=(deg[i]==2);
    	vec[++len]=ans;
    }
    void solve(int t){
    	if (t==1) solve1(); //直径
    	if (t==2) solve2(); //二度点个数
    	if (t==3) solve3(); //deg的平方和
    	if (t==4) solve4(); //deg的方差 
    	if (t==5) solve5(); //以1为根的子树大小之和
    	if (t==6) solve6(); //以1为根的子树大小的平方和
    	if (t==7) solve7(); //以1为根的子树大小的方差
    	if (t==8) solve8(); //重心的最大子树大小
    	if (t==9) solve9(); //我也不知道这个是在干啥。。。
    	if (t==10) solve10(); //每个点子树中最长链+次长链的长度
    	if (t==11) solve11(); //每个点各个子树大小的对数之和
    	if (t==12) solve12(); //每个点到最远一度点距离的平方和
    	if (t==13) solve13(); //一度点个数-二度点个数
    	if (t==14) solve14(); //每个点子树中最长链平方+次长链平方
    }
    inline void addedge(int u, int v){
    	edgenum++;
    	vet[edgenum]=v;
    	Next[edgenum]=Head[u];
    	Head[u]=edgenum;
    }
    int main(){
    	scanf("%d%d%d",&L,&tp,&tq);
    	//L为随机撒点的个数,tp为生成树的方法(标号与题目中相同),tq为尝试的不同函数的编号
    	signed a[5000],sum;
    	for (int i=0; i<5000; i++) sum+=a[i];
    	srand(sum);
    	for (int o=1; o<=L; o++){
    		gen(tp);
    		memset(deg,0,sizeof(deg));
    		memset(Head,0,sizeof(Head)); edgenum=0;
    		for (int i=1; i<1000; i++){
    			addedge(x[i],y[i]),addedge(y[i],x[i]);
    			deg[x[i]]++,deg[y[i]]++;
    		}
    		solve(tq);
    		if (o%1000==0) printf("==>%d times\n",o); //表示目前撒了多少样本点了
    	}
    	ll mn=1e18,mx=-1e18;
    	for (int i=1; i<=L; i++) mx=max(mx,vec[i]),mn=min(mn,vec[i]);
    	printf("%lld %lld\n",mn,mx);  //特征值的范围
    	
    	ll P=0; scanf("%lld",&P); //给出均分[min,max]的长度
    	ll cur=mn; int tot=0;
    	while (cur<=mx){
    		D[++tot]=cur;
    		U[tot]=(cur+P-1>=mx?mx:cur+P-1);
    		cur+=P;
    	}
    	for (int i=1; i<=L; i++)
    		for (int j=tot; j>=1; j--)
    			if (vec[i]<=U[j] && vec[i]>U[j-1]){ pos[j]++; break; }
    	for (int i=1; i<=tot; i++) printf("%lld %lld %d\n",D[i],U[i],pos[i]); //表示特征值在[D,U]中的样本点个数
    	return 0;
    }
    
    • 1

    信息

    ID
    208
    时间
    3000ms
    内存
    256MiB
    难度
    10
    标签
    递交数
    14
    已通过
    0
    上传者