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 ...
随机推荐
- java 并发——synchronized
java 并发--synchronized 介绍 在平常我们开发的过程中可能会遇到线程安全性的问题,为了保证线程之间操作数据的正确性,我们第一想到的可能就是使用 synchronized 并且 syn ...
- Java finally块
try块也可以有零个或一个finally块. finally块总是与try块一起使用. 语法 finally块的语法是: 1 2 3 finally { // Code for finall ...
- Mysql 生成随机数字
其实思路很简单,利用MySQL现有的函数,然后进行加工处理,达到预期的结果.可以用到的MySQL函数为rand() ,以及 round() 函数. 具体为:select round(rand()*10 ...
- Could not autowire. No beans of 'int' type found. less... (Ctrl+F1) Checks autowiring problems in a bean class.
package com.cxy.netty.controller; import io.netty.bootstrap.ServerBootstrap; import io.netty.channel ...
- arcpy-栅格转其他格式
import arcpy in_format=arcpy.GetParameterAsText(0) out_format=arcpy.GetParameterAsText(1) out_folder ...
- 四、hibernate的缓存
缓存: 就是将数据保存到内存中,需要使用时直接从内存中获取,不需要每次查询数据库或者磁盘中的文件 hibernate的缓存 一级缓存:Session级别的缓存 二级缓存:SessionFactory级 ...
- MySQL字符集不一致导致查询SQL性能问题
今天做了一个MySQL数据库中的SQL优化. 结论是关联字段字符集不同,导致索引不可用. 查询的SQL如下: select `Alias`.`Grade`, `Alias`.`id`, `Alias` ...
- ASE团队项目alpha阶段Frontend组 scrum2 记录
ASE团队项目alpha阶段Frontend组 scrum2 记录 本次会议于11.5日, 11:30在微软北京西二楼13158研讨室,讨论持续15分钟 与会人员:Jingyi Xie, Jiaqi ...
- 关于KiCAD
关于KiCAD 使用背景 一直以来公司都在用AD作为EDA软件,但是最近公司频繁收到律师函,所以决定找一款开源的软件来代替AD,目前市场上开源的只找到了KiCAD和Easy EDA(中文版立创EDA) ...
- IT书单-持续更新
重构:改善既有代码的设计代码整洁之道深入理解Java虚拟机Java并发编程的艺术<修改代码的艺术><程序员的职业素养>代码大全程序员修炼之道深入理解java虚拟机Java并发编 ...