传送门

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

首先完全图上直接输出边权 \(\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. python 07篇 内置函数和匿名函数

    一.内置函数 # 下面这些要掌握 # len type id print input open # round min max filter map zip exec eval print(all([ ...

  2. 建立属于自己的scrapy crawl模板

    本人安装PYTHON3.7安装位置:D:\Python\Python37模板位置:D:\Python\Python37\Lib\site-packages\scrapy\templates\spide ...

  3. c语言:scanf()高级应用

    1) 指定读取长度 还记得在 printf() 中可以指定最小输出宽度吗?就是在格式控制符的中间加上一个数字,例如,%10d表示输出的整数至少占用 10 个字符的位置: 如果整数的宽度不足 10,那么 ...

  4. DEV C++ CPU窗口

    push rbp#push实现压入操作的指令,将指定内存地址或操作数压入堆栈(先进后出)mov rbp,rsp# 将rsp所保存的地址或操作数送到目的操作数rbp(修改rbp内容)sub rsp,0x ...

  5. __schedule的一些小细节

    (代码主要参考5.10) 1. __schedule的参数preempt static void __sched notrace __schedule(bool preempt) preempt是一个 ...

  6. final修饰符(4)-"宏替换"

    对于一个final变量来说,不管它时类变量,实例变量还是局部变量,只要满足三个条件,这个final变量就不再是一个变量,而是一个直接量.final变量的一个重要用途,就是定义"宏变量&quo ...

  7. Motion Planning 是什么

    前言与引用 这一个呢,主要是自己突然看一篇论文的时候不知道 为什么他提出的方法对于规划来说就是好的,规划又应该分为哪几个部分,解决的是哪几个部分的问题?带着这个问题,我就去搜:Motion Plann ...

  8. java网络编程基础——网络基础

    java网络编程 网络编程基础 1.常用的网络拓扑结构: 星型网络.总线网络.环线网络.树形网络.星型环线网络 2.通信协议的组成 通信协议通常由3部分组成: 语义部分:用于决定通信双方对话类型 语法 ...

  9. 搭建SAMBA服务

    说明:这里是Linux服务综合搭建文章的一部分,本文可以作为单独搭建SABMA服务的参考. 注意:这里所有的标题都是根据主要的文章(Linux基础服务搭建综合)的顺序来做的. 如果需要查看相关软件版本 ...

  10. Select、Poll、Epoll IO复用技术

    简介 目前多进程方式实现的服务器端,一次创建多个工作子进程来给客户端提供服务, 但是创建进程会耗费大量资源,导致系统资源不足 IO复用技术就是让一个进程同时为多个客户端端提供服务 IO复用技术 之 S ...