题目大意:

给定n个点 m条边没有重边的仙人掌图(没有一条边会同时存在与两个环 也就是环都是相互独立的)

求任意两点间 i^j^maxflow(i,j)的总和 maxflow为两点间最大流

题解:https://blog.csdn.net/du_lun/article/details/81610624

对于两点间的最大流

若是一个环上的两点 那么最大流就会等于两条路径上的最短边的总和

那么任意两点间的最大流 就是其余边加上最短边后去掉最短边

这样这个图就变成了一棵树

此时按边长逆序排序 取出一条边求最大流 然后将两个分量合并成一个点

取出的边长就是两个联通分量间的最大流 因为每次取出的都是比之前取出的更小的边

求异或值不能n^2枚举两点 按数的32位枚举

每次合并联通分量后 更新这个联通分量中每一个二进制位有多少0 1

当两个联通分量间的最大流

第 j 位为1时 那么使得该位异或后为1 两个联通分量的第j位应为 1 1 或 0 0

第 j 位为0时 那么使得该位异或后为1 两个联通分量的第j位应为 1 0 或 0 1

组合一下 方案数乘以 2^j 就是最大流第 j 位的贡献

这题会爆long long 需要用unsigned long long

#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define LLINF 0x3f3f3f3f3f3f3f3f
#define LL long long
#define mem(i,j) memset(i,j,sizeof(i))
const int N=1e5+; struct EDGE {
int u,v,nt; LL w;
bool operator <(const EDGE& e)const {
return w>e.w;
}
}E[N<<],e[N<<],t[N<<]; // 图的邻接表 树边集 暂存
int head[N], tot, cnt;
void addE(int u,int v,LL w) {
E[tot].u=u, E[tot].v=v;
E[tot].w=w, E[tot].nt=head[u];
head[u]=tot++;
} int low[N], ind, dfn[N], fa[N]; int pos[N]; // 记录走过的环上 i点对应的边在邻接表中的索引
void cir(int u,int v,int id) {
int c=, k=v;
while(k!=u) {
t[c++]=E[pos[k]], k=fa[k];
} // t暂存环上的所有边
t[c++]=E[id];
LL mini=LLINF;
for(int i=;i<c;i++) // 找到最短边
if(t[i].w<mini) mini=t[i].w, k=i;
for(int i=;i<c;i++) // 其他边加上最短边长 存入数边集
if(i!=k) t[i].w+=mini, e[cnt++]=t[i];
} void tarjan(int u,int f) {
dfn[u]=low[u]=++ind;
fa[u]=f;
for(int i=head[u];~i;i=E[i].nt) {
int v=E[i].v;
if(v==f) continue;
if(!dfn[v]) {
pos[v]=i, tarjan(v, u);
low[u]=min(low[u],low[v]);
} else low[u]=min(low[u],dfn[v]);
}
for(int i=head[u];~i;i=E[i].nt) {
int v=E[i].v;
if(low[v]>dfn[u]) e[cnt++]=E[i]; // 树边
// v以及其子孙节点连的所有点中dfn最小的点比u还小
// 说明u往下有一个环且v在环中 那么此时u到v的这条边为树边
else if(dfn[v]>dfn[u] && fa[v]!=u) cir(u,v,i); // 环
}
} int f[N];
int getf(int x) {
if(f[x]==x) return x;
else return f[x]=getf(f[x]);
}
int n, m;
LL c[N][][];
// c[i][j][0/1]是第i个联通分量二进制的第j位为0 1的数量
unsigned long long ans;
void init() {
tot=cnt=ind=; ans=;
for(int i=;i<=n;i++) {
head[i]=-; f[i]=i;
dfn[i]=;
for(int j=;j<=;j++)
c[i][j][]=(i>>j)&, c[i][j][]=((i>>j)&)^;
}
} int main()
{
int t; scanf("%d",&t);
while(t--) {
scanf("%d%d",&n,&m);
init();
while(m--) {
int u,v; LL w; scanf("%d%d%lld",&u,&v,&w);
addE(u,v,w); addE(v,u,w);
}
tarjan(,-);
sort(e,e+cnt);
for(int i=;i<cnt;i++) {
int fu=getf(e[i].u);
int fv=getf(e[i].v);
LL w=e[i].w;
for(int j=;j<=;j++)
if(w&(1LL<<j)) {
ans+=c[fu][j][]*c[fv][j][]*(1LL<<j);
ans+=c[fu][j][]*c[fv][j][]*(1LL<<j);
} else {
ans+=c[fu][j][]*c[fv][j][]*(1LL<<j);
ans+=c[fu][j][]*c[fv][j][]*(1LL<<j);
}
f[fu]=fv;
for(int j=;j<=;j++)
c[fv][j][]+=c[fu][j][],
c[fv][j][]+=c[fu][j][];
}
printf("%llu\n",ans);
} return ;
}

hdu6350 /// tarjan+并查集+组合+最大流思想的更多相关文章

  1. LCA tarjan+并查集POJ1470

    LCA tarjan+并查集POJ1470 https://www.cnblogs.com/JVxie/p/4854719.html 不错的一篇博客啊,让我觉得LCA这么高大上的算法不是很难啊,嘻嘻嘻 ...

  2. BestCoder冠军赛 - 1009 Exploration 【Tarjan+并查集缩点】

    [题意] 给一个图,这个图中既有有向边,又有无向边,每条边只能走一次,问图中是否存在环. 最多10^6个点,10^6个无向边,10^6个有向边 [题解] 因为既有有向边又有无向边,所以不能单纯的用ta ...

  3. POJ3694 Network - Tarjan + 并查集

    Description 给定$N$个点和 $M$条边的无向联通图, 有$Q$ 次操作, 连接两个点的边, 问每次操作后的图中有几个桥 Solution 首先Tarjan找出边双联通分量, 每个双联通分 ...

  4. hdu-2874 Connections between cities(lca+tarjan+并查集)

    题目链接: Connections between cities Time Limit: 10000/5000 MS (Java/Others)     Memory Limit: 32768/327 ...

  5. codeforce 505 D. Mr. Kitayuta's Technology(tarjan+并查集)

    题目链接:http://codeforces.com/contest/505/problem/D 题解:先用tarjan缩点然后再用并查集注意下面这种情况 ‘ 这种情况只需要构成一个大环就行了,也就是 ...

  6. LCA(最近公共祖先)离线算法Tarjan+并查集

    本文来自:http://www.cnblogs.com/Findxiaoxun/p/3428516.html 写得很好,一看就懂了. 在这里就复制了一份. LCA问题: 给出一棵有根树T,对于任意两个 ...

  7. 牛客多校第九场 E All men are brothers 并查集/组合论

    题意: 一开始有n人互不认识,每回合有两个人认识,认识具有传递性,也就是相互认识的人组成小团体.现在问你每个回合,挑选四个人,这四个人互不认识,有多少种挑选方法. 题解: 认识不认识用并查集维护即可, ...

  8. 并查集+启发式合并+LCA思想 || 冷战 || BZOJ 4668

    题面:bzoj炸了,以后再补发 题解: 并查集,然后对于每个点记录它与父亲节点联通的时刻 tim ,答案显然是 u 到 v 的路径上最大的 tim 值.启发式合并,把 size 小的子树往大的上并,可 ...

  9. 并查集算法Union-Find的思想、实现以及应用

    并查集算法,也叫Union-Find算法,主要用于解决图论中的动态连通性问题. Union-Find算法类 这里直接给出并查集算法类UnionFind.class,如下: /** * Union-Fi ...

随机推荐

  1. Jackson教程

    Jackson是一个简单基于Java应用库,Jackson可以轻松的将Java对象转换成json对象和xml文档,同样也可以将json.xml转换成Java对象.Jackson所依赖的jar包较少,简 ...

  2. overflow:hidden失效

    overflow:hidden失效 为了页面的健壮性,我们常常需要使用overflow:hidden.有时候是为了防止布局被撑开,有时候是为了配合其它规则实现文字截断,还有时候纯粹是为了创建块级上下文 ...

  3. c++计算1到100以内的质数

    自考c++实践的时候,有个求计算1-100的质数的问题,没搞出来 由于考试使用的是Dev-C++开发工具,为了下次考试做准备,改用该工具,直接下载安装即可,不会涉及到什么破解等 下载地址:https: ...

  4. Spring Cloud Eureka自我保护机制

    自我保护背景 首先对Eureka注册中心需要了解的是Eureka各个节点都是平等的,没有ZK中角色的概念, 即使N-1个节点挂掉也不会影响其他节点的正常运行. 默认情况下,如果Eureka Serve ...

  5. Java对象引用四个级别(强、软、弱、虚)

    最近,高级Java技术栈微信群中,有一些猿友在讨论JVM中对象的周期问题,有谈到引用的级别,现在为大家做个总结吧,虽然大多数公司并没有意识或者用到这些引用,但了解这些基本概念对熟悉整个垃圾回收机制和面 ...

  6. 35-python基础-python3-字符串修改大小写的方法-title()方法-lower()方法-upper()方法

    1-title()-注:不是原地修改,有返回值 以首字母大写的方式显示每个单词,即将每个单词的首字母都改为大写. 2-lower()和upper()-注:不是原地修改,有返回值 将字符串改为全部小写或 ...

  7. css中的居中问题

    前两天写了一篇关于display:table的用法,里面涉及到居中的问题,这两天愈发觉得css中的居中是一个值得关注的问题,现总结如下. 一.垂直居中 (1)inline或者inline-*元素 1. ...

  8. GitHub-Hexo-Blog 集成Gitalk评论插件

    在本文)末尾可查看先查看效果: 1. 新建New OAuth App 在github中,Settings / Develpoer settings OAuth Apps / New OAuth App ...

  9. STL_Algorithm

    #include <algorithm> #include <cstdio> using namespace std; /*虽然最后一个排列没有下一个排列,用next_perm ...

  10. 【Luogu】【关卡2-1】简单的模拟(2017年10月)

    任务说明:开始普及组的训练!所谓模拟,就是直接根据题意编写,思维难度简单. 铺地毯 进制转换 多项式输出 机器翻译 排座椅 笨小猴 都是简单模拟题