zoukankan      html  css  js  c++  java
  • UVA

    题面在这里!

        一开始看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
    ",i,ans[i]);
    	
    	return 0;
    }
    
  • 相关阅读:
    LeetCode 515. 在每个树行中找最大值(Find Largest Value in Each Tree Row)
    LeetCode 114. 二叉树展开为链表(Flatten Binary Tree to Linked List)
    LeetCode 199. 二叉树的右视图(Binary Tree Right Side View)
    LeetCode 1022. 从根到叶的二进制数之和(Sum of Root To Leaf Binary Numbers)
    LeetCode 897. 递增顺序查找树(Increasing Order Search Tree)
    LeetCode 617. 合并二叉树(Merge Two Binary Trees)
    LeetCode 206. 反转链表(Reverse Linked List) 16
    LeetCode 104. 二叉树的最大深度(Maximum Depth of Binary Tree)
    LeetCode 110. 平衡二叉树(Balanced Binary Tree) 15
    LeetCode 108. 将有序数组转换为二叉搜索树(Convert Sorted Array to Binary Search Tree) 14
  • 原文地址:https://www.cnblogs.com/JYYHH/p/9298354.html
Copyright © 2011-2022 走看看