题目大意:

给定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. UVA1152_4 Values whose Sum is 0

    中途相遇法,这题目总结后我感觉和第一篇博客很像,他们都取了中间,也许这就是二分的魅力吧 这题题意就是从ABCD四个集合中选四个元素使他们的和为0 题意很简单,但是实现起来很容易超时,不能一个一个枚举 ...

  2. jmeter 不同线程组之间传递变量3

    jemter编写脚本要点: 1.切记:BeanShell PostProcessor写在关联函数 Regular Expression Extractor的后面 2.header  HTTP Head ...

  3. Linux部分常用命令详解(一)

    echo 命令详解 格式: echo string 显示普通字符: echo "it is a test" 或者 echo it is a test 显示转义字符: echo &q ...

  4. 微信小程序的加载机制和运行机制

    一.运行机制 冷启动指的是重新启动,热启动指的是5分钟内从后台切换到前台,只有冷启动才能加载最新的包. 小程序什么时候会关闭? 5min后台运行,连续收到两次(2s)系统告警. 二.加载机制 三.小程 ...

  5. texinfo - 软件文档系统

    DESCRIPTION 描述 Texinfo 是一种文档系统,使用单一的源文件来产生在线文档以及可打印的输出.它主要用于书写软件使用手册. 要查看 Texinfo 语言和相关工具的全面描述,请查看 T ...

  6. JAVA基础学习-多态 对象转型 final

    一.多态的产生条件 1:继承  存在继承的类之间 2:方法重装 3:父类继承子类重装的方法 子类的对象 也是属于父类的 二:对象的转型 1:向上转型:当子类转型成父类时 例如:Animal a = n ...

  7. SecureCRT无法删除和退格的解决办法

    一   选项中,设置自动保存 二   选项=>会话选项 选择linux终端.然后在映射键中,选择delete 等映射信息

  8. OK。第一个shell script 脚本

    很简单吧.也很容易理解.读取两个字符放到变量firstname和lastname中,然后输出 编辑日期格式 上面是编辑日期格式.下面的例题是按照日期格式来分类创建文件

  9. 【错误总结】Component template should contain exactly one root element. If you are using v-if on multiple elements, use v-else-if to chain them instead.

    大致意思是因为模板里面应该包含一个根元素,使用组件的时候应该用div或p标签包起来

  10. table响应式设计

    table不可用flex布局和td宽度的自适应. table外层加div.mml-table设置overflow-x:auto可以添加横向滚动条.