2439 四叶草魔杖
问题描述
魔杖护法Freda融合了四件武器,于是魔杖顶端缓缓地生出了一棵四叶草,四片叶子幻发着淡淡的七色光。圣剑护法rainbow取出了一个圆盘,圆盘上镶嵌着N颗宝石,编号为0~N-1。第i颗宝石的能量是Ai。如果Ai>0,表示这颗宝石能量过高,需要把Ai的能量传给其它宝石;如果Ai<0,表示这颗宝石的能量过低,需要从其它宝石处获取-Ai的能量。保证∑Ai =0。只有当所有宝石的能量均相同时,把四叶草魔杖插入圆盘中央,才能开启超自然之界的通道。
不过,只有M对宝石之间可以互相传递能量,其中第i对宝石之间无论传递多少能量,都要花费Ti的代价。探险队员们想知道,最少需要花费多少代价才能使所有宝石的能量都相同?
输入格式
第一行两个整数N、M。
第二行N个整数Ai。
接下来M行每行三个整数pi,qi,Ti,表示在编号为pi和qi的宝石之间传递能量需要花费Ti的代价。数据保证每对pi、qi最多出现一次。
输出格式
输出一个整数表示答案。无解输出Impossible
样例输入
3 3
50 -20 -30
0 1 10
1 2 20
0 2 100
样例输出
30
提示
对于 50% 的数据,2<=N<=8。
对于 100% 的数据,2<=N<=16,0<=M<=N*(N-1)/2,0<=pi,qi<N,-1000<=Ai<=1000,0<=Ti<=1000,∑Ai=0。
做法一:最小生成树+状压dp
枚举点集,若当前点集构成联通块且能量之和为0,显然当前联通块传递能量的最小代价是其最小生成树,因此将每个这样的联通块看成一个物品,背包dp算出最小费用即可。
代码:
#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
struct node{
int x,y,z;};
bool cmp(node a,node b)
{
return a.z<b.z;}
int n,m,A[20],S[66666],V[66666],F[66666],TOT;
int fa[20];
bool mark[20];
node P[200];
int GF(int x)
{
if(fa[x]!=x)fa[x]=GF(fa[x]);
return fa[x];
}
int Kruscal(int s)
{
int i,j,fx,fy,x,y,k=1,tot=0,cnt=0,ans=0;
memset(mark,0,sizeof(mark));
for(i=1;i<=n;i++)if((1<<i-1)&s)tot++,mark[i]=1;
for(i=1;i<=n;i++)fa[i]=i;
while(k<=m&&cnt<tot)
{