Description
- 给一个无向图,每条边有长度,问最长的点数为k的简单路径的长度。
- n<=1e4,m<=1e4,k<=6,极限数据组数<=5
Solution
- 一种神奇的思路。
- 给每一个点随机一个在k以内的颜色,再根据颜色进行状压DP并保证路径上的颜色都是不一样的(这样强行确定为简单路径)
- 这样做一次的成功率为kkk!,约为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);
}
}