• 【随机编号】【 2019 Multi-University Training Contest 8】1008.Andy and Maze


    Description

    • 给一个无向图,每条边有长度,问最长的点数为k的简单路径的长度。
    • n<=1e4,m<=1e4,k<=6,极限数据组数<=5

    Solution

    • 一种神奇的思路。
    • 给每一个点随机一个在k以内的颜色,再根据颜色进行状压DP并保证路径上的颜色都是不一样的(这样强行确定为简单路径)
    • 这样做一次的成功率为k!kkfrac{k!}{k^k},约为0.16,随机很多次(看情况而定)后答案就有可能正确了。
    #include<cstdio>
    #include<cmath>
    #include<cstring>
    #include<algorithm>
    #define maxn 10005
    #define maxm 20005
    #define Time 200
    #define inf 1e9
    using namespace std;
    
    int T,n,m,k,i,j,x,y,z,S;
    int em,e[maxm],nx[maxm],ls[maxn],ec[maxm];
    int col[maxn],f[maxn][1<<6],ans;
    
    void Max(int &x,int y){x=max(x,y);}
    
    void insert(int x,int y,int z){
    	em++; e[em]=y; nx[em]=ls[x]; ls[x]=em; ec[em]=z;
    	em++; e[em]=x; nx[em]=ls[y]; ls[y]=em; ec[em]=z;
    }
    
    int nows=0,a=3,b=267,c=19,d=983,mo=19260817;
    void rd(){
    	for(i=1;i<=n;i++){
    		nows=(a*nows*nows*nows+b*nows*nows+c*nows+d)%mo;
    		nows=(nows+mo)%mo;
    		col[i]=nows%k;
    	}
    }
    
    int main(){
    	scanf("%d",&T);
    	while (T--){
    		scanf("%d%d%d",&n,&m,&k);
    		em=0;memset(ls,0,sizeof(ls));
    		for(i=1;i<=m;i++){
    			scanf("%d%d%d",&x,&y,&z);
    			insert(x,y,z);
    		}
    		ans=-inf;
    		for(int time=1;time<=Time;time++){
    			rd();
    			memset(f,128,sizeof(f));
    			for(i=1;i<=n;i++) f[i][1<<col[i]]=0;
    			for(S=1;S<(1<<k)-1;S++) {
    				for(x=1;x<=n;x++) if (f[x][S]>-inf)
    					for(i=ls[x];i;i=nx[i]) if (!(S&(1<<col[e[i]]))) 
    						Max(f[e[i]][S^(1<<col[e[i]])],f[x][S]+ec[i]);
    			}
    			for(i=1;i<=n;i++) ans=max(ans,f[i][(1<<k)-1]);
    		}
    		if (ans==-inf) printf("impossible
    "); else printf("%d
    ",ans);
    	}
    }
    
  • 相关阅读:
    Java遍历Map、List、Array
    自签名SSL生成
    oracle_round
    Timestamp_时间戳
    oracle_substr
    eval
    orcale_聚合函数
    oracle_decode
    js_JSON
    sql拼接
  • 原文地址:https://www.cnblogs.com/DeepThinking/p/13090971.html
Copyright © 2020-2023  润新知