题目链接:Andy and Maze
题意:n个房间,每个房间里有一块宝石,m条无向边连接,经过每条路径都有花费,到达每个房间可以获得一块宝石,获得k块就可以逃离迷宫,但是这条获得宝石的路径上同一个房间不能进入多次,你不知道哪里是起点,问满足条件的路径最多花费多少;
分析:color coding算法(一种随机算法),大概思路是给n个节点分别染色,使得一条路径上两两不同,更新答案,于是就可以加上状压dp处理状态;
#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
using namespace std;
const int maxn=1e4+7;
const int limit=300;
struct node{int u,v,w;} g[maxn];
int col[maxn],dp[maxn][1<<6];
int n,m,k;
void getcolor() {for (int i=1;i<=n;i++) col[i]=rand()%k;}
int getans()
{
int mx=(1<<k);
for (int i=1;i<=n;i++)
{
for (int j=0;j<mx;j++) dp[i][j]=-INF;
dp[i][1<<col[i]]=0;
}
for (int j=0;j<mx;j++)
for (int i=1;i<=m;i++)
{
int u=g[i].u,v=g[i].v,w=g[i].w;
if(j & (1<<col[u])) dp[u][j]=max(dp[u][j],dp[v][j^(1<<col[u])]+w);
if(j & (1<<col[v])) dp[v][j]=max(dp[v][j],dp[u][j^(1<<col[v])]+w);
}
int res=-1;
for (int i=1;i<=n;i++) res=max(res,dp[i][mx-1]);
return res;
}
void rua()
{
scanf("%d%d%d",&n,&m,&k);
for (int i=1;i<=m;i++) scanf("%d%d%d",&g[i].u,&g[i].v,&g[i].w);
int ans=-1;
for (int i=1;i<=limit;i++)
{
getcolor();
ans=max(ans,getans());
}
if(ans==-1) printf("impossible\n");
else printf("%d\n",ans);
return ;
}
int main()
{
int T;scanf("%d",&T);
while (T--) rua();
return 0;
}