Problem C Dist

Description

有一个\(n\)个点带边权的连通无向图,边集用\(k\)个集合\(s_1,s_2,\dots,s_k\)和\(k\)个整数\(w_1,w_2,\dots,w_k\)来表示,\((s_i,w_i)\)表示\(\forall u,v\in s_i (u\not=v)\),\(\exists E(u,v)=w_i\)

求\(\sum_{i=1}^n\sum_{j=1}^{i-1}dist(i,j)\),\(dist(i,j)\)代表\(i\)点到\(j\)点的最短路。

Input

第一行两个整数\(n,k\)。

接下来\(k\)行,每行前两个整数表示\(k_i,|s_i|\),接下来的\(|s_i|\)个整数表示\(s_i\)中的元素,保证集合非空且给出的元素两两不同。

Output

输出一个整数表示答案。

HINT

\(1\le n\le 10^5,1\le k \le 18,1\le w_i\le 10^7,\sum|s_i|\le3\times 10^5\)


其实这种题看起来不太好想,但是可能没那么难,就是考查一些枚举技巧和小trick之类的。

首先团才那么几个,这就给了一个关于集合的思维导向性。

不妨把团抽象成点,先求出团之间的两两最短路。这里有边的条件是团的并不为空,最短路是点权和最小。

然后枚举每一个点\(x\),然后把\(x\)到团的距离从小到大进行排序,一个团一个团的向里面加。

当前加团时,产生的贡献为\(x\)到团的最短距离乘上可以做出贡献的点数,可以做出贡献的点是之前加进去的团没有出现过的。

这里预处理一个\(cnt_{i,s}\)代表 在第\(i\)个团 但不在\(s\)中的\(1\)对应的团 的\(x\)的个数。

预处理这个需要快速求解子集和的技巧,就是\(FMT\)里面的一个小trick吧


Code:

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <bitset>
#define ll long long
const int N=1e5+10;
const int M=20;
const int inf=0x3f3f3f3f;
std::bitset <N> hav[M];
struct node
{
int w,id;
bool friend operator <(node n1,node n2){return n1.w<n2.w;}
node(){}
node(int w,int id){this->w=w,this->id=id;}
}dis[M];
using std::min;
int n,m,wei[M],be[N],g[M][M],cnt[M][1<<M];
int main()
{
scanf("%d%d",&n,&m);
for(int s,i=1;i<=m;i++)
{
scanf("%d%d",wei+i,&s);
for(int x,j=1;j<=s;j++)
{
scanf("%d",&x);
be[x]|=1<<i-1;
hav[i][x]=1;
}
}
for(int j=1;j<=m;j++)
for(int i=1;i<=n;i++)
if(be[i]>>j-1&1)
++cnt[j][be[i]];
for(int k=1;k<=m;k++)
{
for(int i=1;i<1<<m;i<<=1)
for(int s=0;s<1<<m;s++)
if(s&i)
cnt[k][s]+=cnt[k][s^i];
for(int s=0;s<1<<m;s++)
{
int t=s^((1<<m)-1);
if(s<t) std::swap(cnt[k][s],cnt[k][t]);
}
}
memset(g,0x3f,sizeof(g));
for(int i=1;i<=m;i++)
for(int j=i+1;j<=m;j++)
if((hav[i]&hav[j]).count()!=0)
g[i][j]=g[j][i]=wei[i]+wei[j];
for(int k=1;k<=m;k++)
for(int i=1;i<=m;i++)
for(int j=1;j<=m;j++)
g[i][j]=min(g[i][j],g[i][k]+g[k][j]-wei[k]);
for(int i=1;i<=m;i++) g[i][i]=wei[i];
ll ans=0;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++) dis[j]=node(inf,inf);
for(int j=1;j<=m;j++)
if(be[i]>>j-1&1)
for(int k=1;k<=m;k++)
dis[k]=min(dis[k],node(g[j][k],k));
std::sort(dis+1,dis+1+m);
int sta=0;
for(int j=1;j<=m;j++)
{
ans+=1ll*dis[j].w*cnt[dis[j].id][sta];
if(j==1) ans-=dis[j].w;
sta|=1<<dis[j].id-1;
}
}
printf("%lld\n",ans>>1);
return 0;
}

2018.12.27

Problem C Dist 解题报告的更多相关文章

  1. ZOJ Problem Set - 1025解题报告

    ZOJ Problem Set - 1025 题目分类:基础题 原题地址:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=10 ...

  2. ACM: A Simple Problem with Integers 解题报告-线段树

    A Simple Problem with Integers Time Limit:5000MS Memory Limit:131072KB 64bit IO Format:%lld & %l ...

  3. BestCoder18 1002.Math Problem(hdu 5105) 解题报告

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5105 题目意思:给出一个6个实数:a, b, c, d, l, r.通过在[l, r]中取数 x,使得 ...

  4. Problem - 433C - Codeforces解题报告

    对于这题本人刚开始的时候的想法是:先把最大两数差的位置找到然后merge计算一个值再与一连串相同的数做merge后计算一个值比较取最大值输出:可提交后发现不对,于是本人就搜了一下正解发现原来这题的正确 ...

  5. Problem A: 选举 解题报告

    Problem A: 选举 题意 给出一个投票过程.有\(n\)个选民和\(m\)个候选人,每个选民\(i\)有个不重且有序的可投集合\(\{a_i\}\). 对于第一轮投票,选民\(i\)会投给\( ...

  6. Problem A: 种树 解题报告

    Problem A: 种树 Description 很久很久以前,一个蒟蒻种了一棵会提问的树,树有\(n\)个节点,每个节点有一个权值,现在树给出\(m\)组询问,每次询问两个值:树上一组点对\((x ...

  7. Problem C: 多线程 解题报告

    Problem C: 多线程 Description 多线程是一种常见的加速手段,利用多个线程同时处理不同的任务可以一定程度上减少总耗时,达到提高效率的目的.然而,多个线程间的执行顺序是完全不可控的, ...

  8. Problem A: 踢罐子 解题报告

    Problem A: 踢罐子 Description 平面上有\(n\)个点,其中任意2点不重合,任意3点不共线. 我们等概率地选取一个点A,再在剩下的\(n-1\)个点中等概率地选取一个点B,再在剩 ...

  9. Problem B: 专家系统 解题报告

    Problem B: 专家系统 Description 一个专家系统是指,你雇佣了\(n\)个专家,他们每个人会做出一个结果,然后你从中选取较多的专家的结果组合而成最终的结果.专家系统广泛应用于传统机 ...

随机推荐

  1. ASP.NET Core 3.0 实战:构建多版本 API 接口

    第一次在博客写分享,请多多捧场,如有歧义请多多包含! 因为业务需求发展需要,所以API接口的变更升级是必不可少的事情,而原有的接口是不可能马上停止使用的.例如:Login接口为例,1.0版本之返回用户 ...

  2. iOS Swift WisdomScanKit图片浏览器功能SDK

    iOS Swift WisdomScanKit图片浏览器功能SDK使用 一:简介      WisdomScanKit 由 Swift4.2版编写,完全兼容OC项目调用. WisdomScanKit的 ...

  3. 2017-2018-2 『网络对抗技术』Exp3:免杀原理与实践

    1. 免杀原理与实践说明 一.实验说明 任务一:正确使用msf编码器,msfvenom生成如jar之类的其他文件,veil-evasion,自己利用shellcode编程等免杀工具或技巧:(1.5分) ...

  4. C# event线程安全

    突然想到有关C#中使用event特性时关于线程安全的问题,以前虽然有遵从“复制引用+null判断”的模式(盲目地),但没有深入了解和思考. 为之查询了资料和实验,对此有了进一步的理解. 一般event ...

  5. Luogu P1983 车站分级

    (一周没写过随笔了) 这道题有坑! 看到题目,发现这么明显(??)的要求顺序,还有什么想法,拓扑! 将每条路范围内等级大于等于它的点(不能重复(坑点1))和它连一条边,注意起点终点都要有(坑点2),然 ...

  6. 汇编 fsub ,fmul,fdiv,fild,CVTTPS2PI 指令

    知识点:  浮点指令 fsub 一.浮点指令fsub 格式 fsub memvar // st0=st0-memvar 知识点:  浮点指令 fmul 一.浮点指令fmul 格式 fmul mem ...

  7. Flutter - 创建底部导航栏

    之前写过的一篇文章介绍了 Flutter - 创建横跨所有页面的侧滑菜单, 这次就一起来学习一下底部导航栏. 底部导航栏在ios平台上非常常见,app store就是这样的风格.还有就是大家最常用的微 ...

  8. .NET Core容器化开发系列(零)——计划

    .NET Core相当完善的跨平台特性以及其轻量化的底层接口为我们能顺畅进行微服务开发提供了非常棒的基础. 作为支撑微服务最常见的基础技术--容器化将是本系列的核心内容. 接下来我计划用一个月左右的时 ...

  9. AppStore下载Xcode的文件

    有的时候团队开发,手机系统一升级,那么对应的Xcode也就需要升级了,由于团队开发,可能一下要把所有人的都升级一下,那么最简单的就是下好一份Xcode然后分享给大家. 但是有的时候你就会发现,通过Ap ...

  10. centos7 lldb 调试netcore应用的内存泄漏和死循环示例(dump文件调试)

    写个demo来玩一玩linux平台下使用lldb加载sos来调试netcore应用. 当然,在真实的产线环境中需要分析的数据和难度远远高于demo所示,所以demo的作用也仅仅只能起到介绍工具的作用. ...