传送门

各种骗分无果,特殊性质还手残写挂了……

首先完全图上直接输出边权 \(\times (n-2)\) 就行了,然而我脑残乘的 \(n-1\)

看数据范围肯定是状压,但是压边肯定炸了,考虑压点

因为1到n路径唯一,最终的图可以看作一条链上挂着数个连通块

根据题解,我们试着从这个方向下手

那这里状压的时候我们既要考虑这条链,又要考虑连通块

发现只有链上的最后一个元素有用,所以令 \(dp[s][k]\) 为已选的点集为 \(s\) ,链的末端为k时的最大边权和

考虑转移,发现我们可以向链的末端挂上一个任意大小的联通块

所以直接暴力 \(O(n^23^n)\) 枚举转移,发现T了

于是大力卡常,预处理优化到 \(O(\frac{n^2}{4}3^n)\) ,发现过了,然后就没有了

其实还可以优化,考虑把「挂任意大小的联通块」拆成「挂一个元素」和「在当前链的末端挂一个连通块,但不改变链的末端元素」两种情况

然后就可以分开转移,可以康康战神代码

Code:

#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define N 100010
#define ll long long
#define reg register int
//#define int long long char buf[1<<21], *p1=buf, *p2=buf;
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf, 1, 1<<21, stdin)), p1==p2?EOF:*p1++)
inline int read() {
int ans=0, f=1; char c=getchar();
while (!isdigit(c)) {if (c=='-') f=-f; c=getchar();}
while (isdigit(c)) {ans=(ans<<3)+(ans<<1)+(c^48); c=getchar();}
return ans*f;
} int n, m;
ll sum; namespace force{
ll ans;
int head[N], size;
bool vis[N], use[N], fa[N];
struct edge{int from, to, next, val;}e[N<<1];
inline void add(int s, int t, int w) {edge* k=&e[++size]; k->from=s; k->to=t; k->val=w; k->next=head[s]; head[s]=size;}
inline bool operator < (edge a, edge b) {return a.val<b.val;}
inline int find(int p) {return fa[p]==p?p:fa[p]=find(fa[p]);}
bool dfs(int u) {
vis[u]=1;
bool yes=0;
for (int i=head[u],v; i; i=e[i].next) {
v = e[i].to;
if (!vis[v]) {
if (dfs(v)) yes=1;
}
}
if (yes) {
use[u]=1;
for (int i=head[u]; i; i=e[i].next)
use[e[i].to]=1;
}
return (u==n)||yes;
}
void kruskal() {
sort(e+1, e+size+1);
for (int i=1,f1,f2; i<=size; ++i) {
f1=find(e[i].from), f2=find(e[i].to);
if (f1!=f2) {
ans+=e[i].val;
}
else if (!(use[e[i].from]&&use[e[i].to])) ans+=e[i].val;
}
}
void solve() {
bool same=1; int lst=0;
for (int i=1,u,v,w; i<=m; ++i) {
u=read(); v=read(); w=read(); sum+=w;
add(u, v, w); add(v, u, w);
if (lst&&w!=lst) same=0;
else lst=w;
}
dfs(1);
if (same && m>=n*(n-1)/2) {printf("%lld\n", 1ll*lst*(n-2)); exit(0);}
//for (int i=1; i<=n; ++i) cout<<use[i]<<' '; cout<<endl;
kruskal();
printf("%lld\n", sum-ans);
exit(0);
}
} namespace task{
ll dp[1<<16][16], sum[1<<16][16], tot;
int mp[16][16], lg[1<<16];
void solve() {
for (int i=1,u,v; i<=m; ++i) {
u=read()-1; v=read()-1;
tot+=(mp[u][v]=mp[v][u]=read());
}
int lim=1<<n; ll tem;
for (int i=0; i<n; ++i) lg[1<<i]=i;
for (reg s=1; s<lim; ++s) {
tem=0;
for (reg i=0; i<n; ++i) if (s&(1<<i))
for (reg j=i+1; j<n; ++j) if (s&(1<<j))
tem+=mp[i][j];
if (s&1) dp[s][0]=sum[s][0]=tem;
else for (reg i=0; i<n; ++i) if (s&(1<<i)) sum[s][i]=tem;
}
for (reg s=1,s2; s<lim; ++s) {
if (!(s&1)) continue;
for (reg s0=s2=(~s)&(lim-1); s0; s0=(s0-1)&s2)
for (reg i=s; i; i-=i&-i)
for (reg j=s0; j; j-=j&-j)
dp[s|s0][lg[j&-j]] = max(dp[s|s0][lg[j&-j]], dp[s][lg[i&-i]]+sum[s0][lg[j&-j]]+mp[lg[i&-i]][lg[j&-j]]);
#if 0
for (reg i=0; i<n; ++i) if (s&(1<<i))
for (reg j=0; j<n; ++j) if (s0&(1<<j)&&mp[i][j]) {
//if (dp[s][i]+sum[s0][j]+mp[i][j] > dp[s|s0][j]) cout<<"new ans"<<endl;
dp[s|s0][j] = max(dp[s|s0][j], dp[s][i]+sum[s0][j]+mp[i][j]);
//cout<<"upd "<<bitset<15>(s)<<' '<<bitset<15>(s0)<<' '<<i<<' '<<j<<' '<<dp[s][i]<<' '<<sum[s0][j]<<' '<<mp[i][j]<<endl;
}
#endif
}
//cout<<"dp: "<<dp[lim-1][n-1]<<endl;
printf("%lld\n", tot-dp[lim-1][n-1]);
exit(0);
}
} signed main()
{
n=read(); m=read();
task::solve(); return 0;
}

题解 Connect的更多相关文章

  1. LeetCode OJ 题解

    博客搬至blog.csgrandeur.com,cnblogs不再更新. 新的题解会更新在新博客:http://blog.csgrandeur.com/2014/01/15/LeetCode-OJ-S ...

  2. Connect the Cities(prime)

    Connect the Cities Time Limit : 2000/1000ms (Java/Other)   Memory Limit : 32768/32768K (Java/Other) ...

  3. usaco training 4.1.3 fence6 题解

    Fence Loops题解 The fences that surround Farmer Brown's collection of pastures have gotten out of cont ...

  4. usaco 2002 月赛 Fiber Communications 题解

    Description Farmer John wants to connect his N (1 <= N <= 1,000) barns (numbered 1..N) with a ...

  5. 【Codeforces Round】 #431 (Div. 2) 题解

    Codeforces Round #431 (Div. 2)  A. Odds and Ends time limit per test 1 second memory limit per test ...

  6. leetcode & lintcode 题解

    刷题备忘录,for bug-free 招行面试题--求无序数组最长连续序列的长度,这里连续指的是值连续--间隔为1,并不是数值的位置连续 问题: 给出一个未排序的整数数组,找出最长的连续元素序列的长度 ...

  7. Codeforces Round #542 [Alex Lopashev Thanks-Round] (Div. 2) 题解

    Codeforces Round #542 [Alex Lopashev Thanks-Round] (Div. 2) 题目链接:https://codeforces.com/contest/1130 ...

  8. CF 1130A 1130B 1130C1129A1 1129A2 1129B(Round542A B C D1 D2 E)题解

    A : Be Positive 题目地址:https://codeforces.com/problemset/problem/1130/A 题解:让你求是否满足一个d使得数列长为n的a数组的每个数除以 ...

  9. 【CodeChef】Find a special connected block - CONNECT(斯坦纳树)

    [CodeChef]Find a special connected block - CONNECT(斯坦纳树) 题面 Vjudge 题解 还是一样的套路题,把每个数字映射到\([0,K)\)的整数, ...

随机推荐

  1. WPF教程十五:数据模板的使用(重发)

    数据模板 数据模板是一段如何显示绑定在VM对象的XAML代码.数据模板可以包含任意元素的组合,基于Binding来显示不同的信息. 在实际的开发中数据模板的应用场景很多,同样一个控件可以根据不同的绑定 ...

  2. Kotlin Coroutine(协程): 三、了解协程

    @ 目录 前言 一.协程上下文 1.调度器 2.给协程起名 3.局部变量 二.启动模式 CoroutineStart 三.异常处理 1.异常测试 2.CoroutineExceptionHandler ...

  3. Java | 变量 & 常量

    变量 Java是一种强类型语言,每个变量都必须声明其数据类型,变量本质上就是代表一个"可操作的存储的空间",在定义之后空间位置是确定的,但是里面放置什么值是不确定的,我们操作的时候 ...

  4. FreeRTOS+LVGL|Freertos+lvgl如何配置lvgl的心跳和任务管理器

    目录 配置lvgl心跳(Tick) 配置lvgl任务管理器(Task Handler) LVGL中文手册 lvgl需要系统滴答声(心跳)才能知道动画和其他任务的经过时间,所以我们必须要配置好lvgl的 ...

  5. Podistributor播客分发系统介绍

    特性 向用户暴露节目的别名 URL ,在用户访问时重定向至真实的目标资源 URL ,以高效地进行 CDN 切换和便捷地建立失效转移机制. 异步转发请求至统计服务,以解耦用户请求和数据统计,可方便地接入 ...

  6. 一文搞懂一致性hash的原理和实现

    在 go-zero 的分布式缓存系统分享里,Kevin 重点讲到过一致性hash的原理和分布式缓存中的实践.本文来详细讲讲一致性hash的原理和在 go-zero 中的实现. 以存储为例,在整个微服务 ...

  7. mysql:insert replace

    在使用SQL语句进行数据表插入insert操作时,如果表中定义了主键,插入具有相同主键的记录会报错: Error Code: 1062. Duplicate entry 'XXXXX' for key ...

  8. 前端小技巧:css sprite----V客学院技术分享

    前端小技巧:css sprite 因为英文名叫sprite,翻译过来是精灵,而雪碧饮料也叫sprite,所以叫精灵兔或者雪碧图. 它有什么作用呢? 当用户在浏览器里输入一个URL地址的时候,你会感觉无 ...

  9. bash shell 遍历一个数组

    var[@]  数组的一个元素 var=("first" "second" "three") for str in ${var[@]}; d ...

  10. 微信小程序云开发-云存储-上传单个视频到云存储并显示到页面上

    一.wxml文件 <!-- 上传视频到云存储 --> <button bindtap="chooseVideo" type="primary" ...