博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
[tyvj2054] 四叶草魔杖 (最小生成树 状压dp)
阅读量:5240 次
发布时间:2019-06-14

本文共 2200 字,大约阅读时间需要 7 分钟。

Background

陶醉在彩虹光芒笼罩的美景之中,探险队员们不知不觉已经穿过了七色虹,到达了目的地,面前出现了一座城堡和小溪田园,城堡前的木牌上写着“Poetic Island”。

“这一定就是另外两位护法的所在地了……我们快进去吧!”
探险队员们快步进入了城堡,城堡大厅的羊毛沙发上坐着两个人。
“你们是Nescafe的护法吧?”
“是的哦~ 我们就是圣剑护法rainbow和魔杖护法freda~ 你们来这里做什么呢~”
“我们是来拜访圣主和四位护法的……”
“可是圣主applepi已经前往超自然之界的学校(Preternatural Kingdom University,简称PKU)修炼魔法了,要想见到他,必须开启Nescafe之塔与超自然之界的通道。但是圣主规定,开启通道的方法不能告诉任何外人。我只能提示你们,开启通道的钥匙就与四位护法有关T_T”
探险队员环视四周,突然,其中一人的目光停留在了魔杖之上。“hoho~ 魔杖!传说中开启异时空通道的钥匙不就叫四叶草魔杖吗?四叶草有力量、信心、希望和幸运四片叶子,护法恰好有神刀、飞箭、圣剑、魔杖四位!aha~我找到答案了!”
“好吧,那我们就满足你们的愿望~”

Description

魔杖护法Freda融合了四件武器,于是魔杖顶端缓缓地生出了一棵四叶草,四片叶子幻发着淡淡的七色光。圣剑护法rainbow取出了一个圆盘,圆盘上镶嵌着N颗宝石,编号为0~N-1。第i颗宝石的能量是Ai。如果Ai>0,表示这颗宝石能量过高,需要把Ai的能量传给其它宝石;如果Ai<0,表示这颗宝石的能量过低,需要从其它宝石处获取-Ai的能量。保证∑Ai =0。只有当所有宝石的能量均相同时,把四叶草魔杖插入圆盘中央,才能开启超自然之界的通道。

不过,只有M对宝石之间可以互相传递能量,其中第i对宝石之间无论传递多少能量,都要花费Ti的代价。探险队员们想知道,最少需要花费多少代价才能使所有宝石的能量都相同?

Input

第一行两个整数N、M。

第二行N个整数Ai。
接下来M行每行三个整数pi,qi,Ti,表示在编号为pi和qi的宝石之间传递能量需要花费Ti的代价。数据保证每对pi、qi最多出现一次。

Output

输出一个整数表示答案。无解输出Impossible。

Sample Input

3 3

50 -20 -30
0 1 10
1 2 20
0 2 100

Sample output

30

Solution

先用状压dp枚举选出所有sum=0的子图

然后对每一个这样的子图进行kruskal求值最后dp统计即可

Code

//By Menteur_Hxy#include
#include
#include
#include
#include
#define LL long long#define M(a,b) memset(a,(b),sizeof(a))#define F(i,a,b) for(register LL i=(a);i<=(b);i++)#define E(i,u) for(register LL i=head[u];i;i=e[i].nxt)using namespace std;LL rd() { LL x=0,f=1; char c=getchar(); while(!isdigit(c)) {if(c=='-')f=-f;c=getchar();} while(isdigit(c)) x=(x<<1)+(x<<3)+c-48,c=getchar(); return x*f;}const int INF=0x3f3f3f3f;const int N=17,M=N*N;int n,m,cnt;LL da[N],sum[1<
<
<
>i)&1) tot++,fa[i]=i; F(i,1,m) if(((x>>e[i].fr)&1) && ((x>>e[i].to)&1)) { int fx=getf(e[i].fr),fy=getf(e[i].to); if(fx!=fy) { fa[fx]=fy; ret++; sum+=e[i].w; } } if(ret+1
>j)&1) sum[i]+=da[j]; F(i,0,MAX) if(!sum[i]) val[i]=kru(i); else val[i]=INF; F(i,0,MAX) dp[i]=INF;dp[0]=0; F(i,0,MAX) if(!sum[i]) //这里必须加判断否则会T qwq F(j,1,MAX) if(!sum[j]) dp[i|j]=min(dp[i|j],dp[i]+val[j]); if(dp[MAX]==INF) return printf("Impossible"),0; else printf("%lld",dp[MAX]); return 0;}

转载于:https://www.cnblogs.com/Menteur-Hxy/p/9291134.html

你可能感兴趣的文章
Item 9: Avoid Conversion Operators in Your APIs(Effective C#)
查看>>
js去除空格
查看>>
学习Spring Boot:(二十八)Spring Security 权限认证
查看>>
IT学习神器——慕课网App获App Store、Android应用市场重磅推荐
查看>>
Linux网络状态工具ss命令使用详解
查看>>
深入浅出JavaScript(2)—ECMAScript
查看>>
编程珠玑第十一章----排序
查看>>
Face The Right Way POJ - 3276 (开关问题)
查看>>
STEP2——《数据分析:企业的贤内助》重点摘要笔记(六)——数据描述
查看>>
变量的命名规范
查看>>
手机端自动跳转
查看>>
react中进入某个详情页URL路劲参数Id获取问题
查看>>
首届.NET Core开源峰会
查看>>
ViewPager的onPageChangeListener里面的一些方法参数:
查看>>
python pdf转word
查看>>
文本相似度比较(网页版)
查看>>
Jenkins关闭、重启,Jenkins服务的启动、停止方法。
查看>>
CF E2 - Array and Segments (Hard version) (线段树)
查看>>
Linux SPI总线和设备驱动架构之四:SPI数据传输的队列化
查看>>
SIGPIPE并产生一个信号处理
查看>>