hdu6350 /// tarjan+并查集+组合+最大流思想
题目大意:
给定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+并查集+组合+最大流思想的更多相关文章
- LCA tarjan+并查集POJ1470
LCA tarjan+并查集POJ1470 https://www.cnblogs.com/JVxie/p/4854719.html 不错的一篇博客啊,让我觉得LCA这么高大上的算法不是很难啊,嘻嘻嘻 ...
- BestCoder冠军赛 - 1009 Exploration 【Tarjan+并查集缩点】
[题意] 给一个图,这个图中既有有向边,又有无向边,每条边只能走一次,问图中是否存在环. 最多10^6个点,10^6个无向边,10^6个有向边 [题解] 因为既有有向边又有无向边,所以不能单纯的用ta ...
- POJ3694 Network - Tarjan + 并查集
Description 给定$N$个点和 $M$条边的无向联通图, 有$Q$ 次操作, 连接两个点的边, 问每次操作后的图中有几个桥 Solution 首先Tarjan找出边双联通分量, 每个双联通分 ...
- hdu-2874 Connections between cities(lca+tarjan+并查集)
题目链接: Connections between cities Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 32768/327 ...
- codeforce 505 D. Mr. Kitayuta's Technology(tarjan+并查集)
题目链接:http://codeforces.com/contest/505/problem/D 题解:先用tarjan缩点然后再用并查集注意下面这种情况 ‘ 这种情况只需要构成一个大环就行了,也就是 ...
- LCA(最近公共祖先)离线算法Tarjan+并查集
本文来自:http://www.cnblogs.com/Findxiaoxun/p/3428516.html 写得很好,一看就懂了. 在这里就复制了一份. LCA问题: 给出一棵有根树T,对于任意两个 ...
- 牛客多校第九场 E All men are brothers 并查集/组合论
题意: 一开始有n人互不认识,每回合有两个人认识,认识具有传递性,也就是相互认识的人组成小团体.现在问你每个回合,挑选四个人,这四个人互不认识,有多少种挑选方法. 题解: 认识不认识用并查集维护即可, ...
- 并查集+启发式合并+LCA思想 || 冷战 || BZOJ 4668
题面:bzoj炸了,以后再补发 题解: 并查集,然后对于每个点记录它与父亲节点联通的时刻 tim ,答案显然是 u 到 v 的路径上最大的 tim 值.启发式合并,把 size 小的子树往大的上并,可 ...
- 并查集算法Union-Find的思想、实现以及应用
并查集算法,也叫Union-Find算法,主要用于解决图论中的动态连通性问题. Union-Find算法类 这里直接给出并查集算法类UnionFind.class,如下: /** * Union-Fi ...
随机推荐
- 如何用QTP录制鼠标右键点击事件
QTP录制鼠标右键单击事件要通过模拟键盘操作来实现 Step 1,修改ReplayType为2,一般情况默认设置是1的.(1 – 使用浏览器事件运行鼠标操作. 2 – 使用鼠标运行鼠标操作)Setti ...
- java jpa 实体关联
关联关系: 1. One to One 2. One to Many 3. Many to One 4 Many to Many 映射: 延迟加载 @Basic(fetch = FetchType.L ...
- (1.1)学习笔记之mysql体系结构(内存、进程、线程)
关键词:mysql体系结构 参考:https://www.cnblogs.com/zhoubaojian/articles/7866292.html 一.mysql体系架构概述 1.mysql体系结构 ...
- yum安装LAMP
安装LAMP环境二进制包安装,先更新yum源,PHP 7.0.33 扩展可选 yum -y install mysql mysql-server mysql-devel httpd httpd-dev ...
- 【Java】 java判断字符串是否为空的方法总结
以下是java 判断字符串是否为空的四种方法: 方法一: 最多人使用的一个方法, 直观, 方便, 但效率很低: if(s == null ||"".equals(s));方法二: ...
- Java-技术专区-技术栈分析辨证方法
1.好多公司动不动就JVM.高并发.分布式.微服务等等,我没有实际经验. 2.从事Java开发三年了,目前的职位是高级Java工程师,感觉技术和工资都到了瓶颈,对以后的发展方向有些迷茫. 3.加班时间 ...
- cordova插件值 二维码扫描
插件地址 https://github.com/gizwits/cordova-gizwits-scan-qrcode 插件安装方式 cordova plugin add https://github ...
- tomcat配置报错解决方法 The jre_home environment variable is not defined correctly
tomcat配置的时候弹出错误,The jre_home environment variable is not defined correctly,难道jre环境变量配置不正确?但是我们又可以执行j ...
- Android蓝牙自动配对Demo,亲测好使!!!(转)
蓝牙自动配对,即搜索到其它蓝牙设备之后直接进行配对,不需要弹出配对确认框或者密钥输入框. 转载请注明出处http://blog.csdn.net/qq_25827845/article/details ...
- win10配置jdk环境变量及遇到的坑
第一步.在系统变量中新增变量命名JAVA_HOME,值为jdk的安装目录 JAVA_HOME C:\Program Files\Java\jdk1.8.0_231 第二步.在系统变量中增加path的值 ...