题目大意:

给定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. Java DOM解析器 - 查询XML文档

    这是需要我们查询的输入XML文件: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 <?xml version="1.0"?> ...

  2. Android组件内核之Fragment管理与内核(二)

    阿里P7Android高级架构进阶视频免费学习请点击:https://space.bilibili.com/474380680本篇文章将先从以下三个内容来介绍Fragment管理与内核: [Fragm ...

  3. gdb调试已在运行中的进程

    一.在服务器上调试进程,服务器上并没有源代码,所以需要将源码上传至服务器,才能调试看到源码,以下是步骤: 1.查看服务进程id:pgrep 服务名 [user@user-MP app]$ pgrep ...

  4. JUnit中Assert简单介绍

    junit中的assert方法全部放在Assert类中,总结一下junit类中assert方法的分类.1.assertTrue/False([String message,]boolean condi ...

  5. vue $attrs 父组件和孙子组件的传值,传函数

    上一篇我们说到provide/inject的依赖注入的传值方法,今天我们来说一下另一个父组件给孙子组件的传值方式$attrs 我们接着上一个例子继续来写 parent父组件 我们给child子组件穿了 ...

  6. 2019-5-21-win10-uwp-url-encode

    title author date CreateTime categories win10 uwp url encode lindexi 2019-5-21 9:54:7 +0800 2018-2-1 ...

  7. The 'with' and 'as' Keywords

    Programming is all about getting the computer to do the work. Is there a way to get Python to automa ...

  8. Java中的杂流(闸总)

    标准输入输出流 System.in: 标准输入流是InputStream的子类对象,字节输入流,只不过是jvm给定的唯一一个从键盘控制条读入的流. public static final InputS ...

  9. 视觉里程计:2D-2D 对极几何、3D-2D PnP、3D-3D ICP

    参考链接:https://mp.weixin.qq.com/s/89IHjqnw-JJ1Ak_YjWdHvA #include <iostream> #include <opencv ...

  10. Minimum Snap轨迹规划详解(3)闭式求解

    如果QP问题只有等式约束没有不等式约束,那么是可以闭式求解(close form)的.闭式求解效率要快很多,而且只需要用到矩阵运算,不需要QPsolver. 这里介绍Nicholas Roy文章中闭式 ...