传送门

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

首先完全图上直接输出边权 \(\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. Activiti7 与 Spring Boot 及 Spring Security 整合 踩坑记录

    1.  前言 实话实说,网上关于Activiti的教程千篇一律,有参考价值的不多.很多都是老早以前写的,基本都是直接照搬官方提供的示例,要么就是用单元测试跑一下,要么排除Spring Security ...

  2. 『心善渊』Selenium3.0基础 — 26、unittest测试框架的断言

    目录 1.断言介绍 2.常用的断言方法 3.断言示例 1.断言介绍 在执行测试用例的过程中,最终用例是否执行通过,是通过判断测试得到的实际结果和预期结果是否相等决定的,这时会用到断言方法. 本着没有消 ...

  3. 海亮NOIP集训-每日总结

    [总结] xzh 2021暑假每日结 2021年7月12日 内容主题 DP,树型DP(讲解人:王修涵) 考场题目总结 T1: 考场简单想法: 算出两两点间距离,贪心,所用时间 \(1.5h\) 左右. ...

  4. 知识全聚集 .Net Core 技术突破 丨ABP vNext 开始

    介绍 很久没有更新博客了,之前想更新但是发现博客园崩了,外加工作上的调换也比较忙,最近有了点时间我来继续更新下这个系列的文章. 今年3月份我带着我们研发组同事,将公司产品从老Abp重构到Abp vNe ...

  5. [刘阳Java]_酷炫视频播放器制作_界面篇

    今天开始分享一篇酷炫播放器制作,包括界面+JS.整个案例非常类似腾讯视频,优酷视频,爱奇艺视频.我们先看一下效果图,然后这篇文章主要界面篇 是不是效果比较酷炫,那么我接着来给大家说一下这个界面设计思路 ...

  6. js扩展函数收集

    1,checkbox序列化 2,form表单对象化 3,数组字符串化

  7. Angular封装WangEditor富文本组件

    富文本组件是web程序中很常用的一个组件,特别是要开发一个博客,论坛这类的网站后台. 得益于Angular的强大,封装WangEditor组件非常简单 1.使用yarn或者npm安装wangedito ...

  8. Odoo开发规范

    本文来源:https://www.jianshu.com/p/e892bf01f036 Odoo开发规范 模块结构 文件夹列表及对应作用 data/:演示和数据文件 models/:模型定义 cont ...

  9. 第十二篇 -- QMainWindow与QAction(剪切-复制-粘贴)

    效果图: 按照上一节的方法,将剪切-复制-粘贴图标放置到工具栏后,为其指定槽函数.这些功能无需自己编写代码来实现,QPlainTextEdit提供了实现这些编辑功能的槽函数,如cut().copy() ...

  10. 编程思想与算法leetcode_二分算法详解

    二分算法通常用于有序序列中查找元素: 有序序列中是否存在满足某条件的元素: 有序序列中第一个满足某条件的元素的位置: 有序序列中最后一个满足某条件的元素的位置. 思路很简单,细节是魔鬼. 二分查找 一 ...