UVA - 11600 Masud Rana

题面在这里!

 

    一开始看n<=30完全没有头绪啊。。。感觉不能二进制状压的样子qwq。

    后来想了想,状态是可以压缩成 目前图中联通块大小集合 和 我们在哪个联通块的,于是开开心心整数拆分,发现n=30的时候也只有5000多,这不是怎么暴力写都能过的复杂度吗233333。

 

    但后来写出来之后发现因为用了太多 vector 以及 map ,还有脸黒自带的大常数,T==100且n全是30的时候就TLE(本地测的)了 qwq。

   

    于是又离线了一波,把n一样的一起回答了(因为n一样的话状态集合就是一样的),终于是过了,130ms,跑的死慢。。。。

 

    看提交里 10ms 的用的直接是二进制状压,迷。。。。

    (感觉自己白写了这么多行代码,mmp)

 

    总结起来就是 : 不开O2少用STL  23333

 

/*
    x = 2/3 * 3 + 1/3 * 1.5 + 1
*/
#include<bits/stdc++.h>
#define ll unsigned long long
using namespace std;
#define pb push_back
const int N=7005;

vector<int> g[N],ask[233];
unordered_map<ll,int> mmp;
int n,T,tot,a[47],m,p[47],siz[47],bg[233];
int Ge[N][35][35],pos[N][35][35],pt[233];
double f[N][35],ans[233];
bool v[N][35],hav[35];

int getf(int x){ return p[x]==x?x:(p[x]=getf(p[x]));}

inline ll gethash(vector<int> x){
	ll an=0;
	for(int i:x) an=an*37ll+(ll)i;
	return an;
}

void dfs(int x,int lef){
	if(lef>=a[x]){
		tot++,a[x+1]=lef;
		for(int i=1;i<=x+1;i++) g[tot].pb(a[i]);
		mmp[gethash(g[tot])]=tot;
	}
	else return;

	for(int i=a[x]?a[x]:a[x]+1;i*2<=lef;i++) a[x+1]=i,dfs(x+1,lef-i);
}

inline void init(){
	for(int i=1;i<=tot;i++) g[i].clear();
	tot=0,mmp.clear(),memset(v,0,sizeof(v));

	dfs(0,n);

	for(int i=1,sz;i<=tot;i++){
		sz=g[i].size();
		for(int j=0;j<sz;j++)
			for(int k=j+1,l;k<sz;k++){
				vector<int> now=g[i];
				now[k]+=now[j],now[j]=0;

				for(l=k;l+1<sz&&now[l]>now[l+1];l++) swap(now[l],now[l+1]);
				pos[i][j][k]=l-1;
				for(l=j;l&&now[l]<now[l-1];l--) swap(now[l],now[l-1]);	

				Ge[i][j][k]=mmp[gethash(now)];
			}
	}
}

void dp(int S,int P){
	if(v[S][P]) return;
	v[S][P]=1,f[S][P]=0;
    if(g[S].size()==1) return;
	f[S][P]=n-1;
    
	for(int i=0,tx,ty;i<P;i++){
		tx=Ge[S][i][P],ty=pos[S][i][P];
		dp(tx,ty),f[S][P]+=f[tx][ty]*g[S][i];
	}

	for(int i=g[S].size()-1,tx,ty;i>P;i--){
		tx=Ge[S][P][i],ty=pos[S][P][i];
		dp(tx,ty),f[S][P]+=f[tx][ty]*g[S][i];
	}

	f[S][P]/=(double)(n-g[S][P]);
}

inline void solve(){
    for(int i=1;i<=30;i++) if(hav[i]){
        n=i,init();
        for(int j=1,tx,ty;j<=T;j++) if(pt[j]==i){
            tx=mmp[gethash(ask[j])],ty=bg[j];
            dp(tx,ty),ans[j]=f[tx][ty];
        }
    }
}

int main(){
	scanf("%d",&T);
	for(int i=1;i<=T;i++){
	    scanf("%d%d",&n,&m),pt[i]=n,hav[n]=1;
	    
	    for(int j=1;j<=n;j++) p[j]=j,siz[j]=1;
	    for(int j=1,uu,vv;j<=m;j++){
	        scanf("%d%d",&uu,&vv);
	        uu=getf(uu),vv=getf(vv);
	        if(uu!=vv) p[uu]=vv,siz[vv]+=siz[uu];
	    }
	    
	    for(int j=1;j<=n;j++) if(getf(j)==j) ask[i].pb(siz[j]);
	    sort(ask[i].begin(),ask[i].end());
	    for(int j=0;j<ask[i].size();j++) if(ask[i][j]==siz[getf(1)]){
	        bg[i]=j; break;
	    }
	}
	
	solve();
	
	for(int i=1;i<=T;i++) printf("Case %d: %.11lf\n",i,ans[i]);
	
	return 0;
}

 

posted @ 2018-07-12 10:52  蒟蒻JHY  阅读(227)  评论(0编辑  收藏  举报