题目大意

  有一个两部各有 \(n\) 个节点的二分图 \(G\),定义 \(G^m\) 为一个 \(m+1\) 层的图,每层有 \(n\) 个节点,相邻两层的诱导子图都和 \(G\) 相同。

  给你 \(m\),求对于所有 \(1\leq i\leq m\),\(G^i\) 的最小生成树的边权和。

  保证图连通。

  \(n,m\leq 100000,\text{边数 }\leq 200000,\text{边权}\leq 30\)

题解

  对于 \(G^i\),先求出用了多少种边权 \(<j\) 的边,再求出用了多少条边权 \(\leq j\) 的边,就可以得到用了多少条边权为 \(j\) 的边。

  那么边权就可以忽略了。

  现在要求出 \(G^i\) 有多少条边。

  从左往右扫,用并查集维护最后两层节点的连通性。

  那么再下一层的并查集肯定会是这两层的并查集加上一点边。

  当我们处理完一层的时候,求出这层新加的边对下一层的贡献。

  这层每加一条边,下一层就要在这两个集合右侧的点之间连边。

  然后不停地往右边传就好了。

  每加一条边就会合并两个集合,所以总共会加 \(O(n)\) 条边。

  时间复杂度:\(O(w(n+m+e)\alpha(n))\)

代码

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#include<ctime>
#include<functional>
#include<cmath>
#include<vector>
#include<assert.h>
//using namespace std;
using std::min;
using std::max;
using std::swap;
using std::sort;
using std::reverse;
using std::random_shuffle;
using std::lower_bound;
using std::upper_bound;
using std::unique;
using std::vector;
typedef long long ll;
typedef unsigned long long ull;
typedef double db;
typedef std::pair<int,int> pii;
typedef std::pair<ll,ll> pll;
void open(const char *s){
#ifndef ONLINE_JUDGE
char str[100];sprintf(str,"%s.in",s);freopen(str,"r",stdin);sprintf(str,"%s.out",s);freopen(str,"w",stdout);
#endif
}
void open2(const char *s){
#ifdef DEBUG
char str[100];sprintf(str,"%s.in",s);freopen(str,"r",stdin);sprintf(str,"%s.out",s);freopen(str,"w",stdout);
#endif
}
int rd(){int s=0,c,b=0;while(((c=getchar())<'0'||c>'9')&&c!='-');if(c=='-'){c=getchar();b=1;}do{s=s*10+c-'0';}while((c=getchar())>='0'&&c<='9');return b?-s:s;}
void put(int x){if(!x){putchar('0');return;}static int c[20];int t=0;while(x){c[++t]=x%10;x/=10;}while(t)putchar(c[t--]+'0');}
int upmin(int &a,int b){if(b<a){a=b;return 1;}return 0;}
int upmax(int &a,int b){if(b>a){a=b;return 1;}return 0;}
const int N=200010;
int f[N];
vector<pii> g[40],a,b;
int find(int x)
{
return f[x]==x?x:f[x]=find(f[x]);
}
int c[N];
int merge(int x,int y)
{
if(find(x)==find(y))
return 0;
if(!c[find(y)])
c[find(y)]=c[find(x)];
f[find(x)]=find(y);
return 1;
}
int n,m,e;
ll ans[N];
ll s[N];
ll d[N];
int main()
{
open("c");
scanf("%d%d%d",&n,&m,&e);
int x,y,w;
for(int i=1;i<=e;i++)
{
scanf("%d%d%d",&x,&y,&w);
g[w].push_back(pii(x,y));
}
for(int i=1;i<=30;i++)
{
a.clear();
for(int j=1;j<=i;j++)
for(auto v:g[j])
a.push_back(v);
for(int j=1;j<=2*n;j++)
f[j]=j;
for(int j=1;j<=m;j++)
d[j]=0;
for(int j=1;j<=2*n;j++)
c[j]=0;
for(auto v:a)
d[1]+=merge(v.first,v.second+n);
b.clear();
for(int j=n+1;j<=2*n;j++)
if(!c[find(j)])
c[find(j)]=j;
else
b.push_back(pii(c[find(j)]-n,j-n));
for(int j=2;j<=m;j++)
{
a=b;
b.clear();
for(auto v:a)
if(find(v.first)!=find(v.second))
{
if(c[find(v.first)]&&c[find(v.second)])
b.push_back(pii(c[find(v.first)]-n,c[find(v.second)]-n));
merge(v.first,v.second);
}
else
d[j]--;
}
for(int j=2;j<=m;j++)
d[j]+=d[j-1];
for(int j=2;j<=m;j++)
d[j]+=d[j-1];
for(int j=1;j<=m;j++)
{
ans[j]+=i*(d[j]-s[j]);
s[j]=d[j];
}
}
for(int i=1;i<=m;i++)
printf("%lld\n",ans[i]);
return 0;
}

【XSY3345】生成树 并查集的更多相关文章

  1. HDU 4786 生成树 并查集+极大极小值 黑白边 确定选择白边的数量

    题意: 给定一个无向图 n 个点 m条无向边 u v val val == 1 表示边(u, v) 为白边 问能否找到n个点的生成树, 使得白边数为斐波那契数 思路: 并查集求图是否连通( 是否存在生 ...

  2. BZOJ 3624: [Apio2008]免费道路 [生成树 并查集]

    题意: 一张图0,1两种边,构造一个恰有k条0边的生成树 优先选择1边构造生成树,看看0边是否小于k 然后保留这些0边,补齐k条,再加1边一定能构成生成树 类似kruskal的证明 #include ...

  3. hdu 1272 判断所给的图是不是生成树 (并查集)

    判断所给的图是不是生成树,如果有环就不是,如果没环但连通分量大于1也不是 find函数 用递归写的话 会无限栈溢出 Orz要加上那一串 手动扩栈 Sample Input6 8 5 3 5 2 6 4 ...

  4. 离线+生成树+并查集——cf1213G

    #include<bits/stdc++.h> using namespace std; #define N 200005 #define ll long long struct Edge ...

  5. 图的生成树(森林)(克鲁斯卡尔Kruskal算法和普里姆Prim算法)、以及并查集的使用

    图的连通性问题:无向图的连通分量和生成树,所有顶点均由边连接在一起,但不存在回路的图. 设图 G=(V, E) 是个连通图,当从图任一顶点出发遍历图G 时,将边集 E(G) 分成两个集合 T(G) 和 ...

  6. UVA 1395 苗条的生成树(最小生成树+并查集)

    苗条的生成树 紫书P358 这题最后坑了我20分钟,怎么想都对了啊,为什么就wa了呢,最后才发现,是并查集的编号搞错了. 题目编号从1开始,我并查集编号从0开始 = = 图论这种题真的要记住啊!!题目 ...

  7. 利用并查集求最大生成树和最小生成树(nlogn)

    hdu1233 还是畅通工程 Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) T ...

  8. Codevs 3287 货车运输 2013年NOIP全国联赛提高组(带权LCA+并查集+最大生成树)

    3287 货车运输 2013年NOIP全国联赛提高组 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 传送门 题目描述 Description A 国有 n 座 ...

  9. 货车运输-洛谷-1967-LCA+最大生成树(kruskal(并查集))

    传送门 一道:LCA+最大生成树 个人认为把这两个的板子写好(并熟练掌握了之后)就没什么难的 (但我还是de了好久bug)qwq 最大生成树:其实就是最小生成树的变形 我用的是kruskal (个人觉 ...

随机推荐

  1. KOA中间件的基本运作原理

    示例代码托管在:http://www.github.com/dashnowords/blogs 博客园地址:<大史住在大前端>原创博文目录 华为云社区地址:[你要的前端打怪升级指南] 在中 ...

  2. elasticsearch health yellow

    csdn博客地址(已测试过):https://blog.csdn.net/yangyangrenren/article/details/81100836 官方地址:https://www.elasti ...

  3. iOS---------获取当前年份

    NSDate *  senddate=[NSDate date]; NSDateFormatter  *dateformatter=[[NSDateFormatter alloc] init]; [d ...

  4. adb 查看 android手机的CPU架构

    adb shell cat  /proc/cpuinfo 当然要下载adb并配置好环境变量

  5. base64图片存储

    将图片转换为Base64编码,可以让你很方便地在没有上传文件的条件下将图片插入其它的网页.编辑器中. 这对于一些小的图片是极为方便的,因为你不需要再去寻找一个保存图片的地方. Base64编码在ora ...

  6. 吴军武志红万维刚薛兆丰何帆曾鸣李笑来罗永浩等得到APP专栏作者的书3

    整理了一下最近两三年内看过的得到APP专栏与课程作者的得到精选文集和他们写过的书共本.新增吴军1本,武志红1本. 其中:武志红3本,熊太行1本,薛兆丰2本,吴军4本,何帆3本,曾鸣2本,万维刚1本,李 ...

  7. 5G来了,中国移动能力开放平台的NFV,支持面向5G的演进,已经具备初期商用条件!

    近日互联网招聘平台发布的<2019春招旺季人才趋势报告>显示,“新新职业”人才受到企业追捧: 5G相关人才需求大幅增长,5G工程师平均招聘月薪达1.39万元,同比增长12.2%.其中,光传 ...

  8. Educational Codeforces Round 60 (Rated for Div. 2) - C. Magic Ship

    Problem   Educational Codeforces Round 60 (Rated for Div. 2) - C. Magic Ship Time Limit: 2000 mSec P ...

  9. 【转】HTTP请求中的form data和request payload的区别

    jQuery的ajax方法和post方法分别发送请求,在后台Servlet进行处理时结果是不一样的,比如用$.ajax方法发送请求时(data参数是一个JSON.stringify()处理后的字符串, ...

  10. [LeetCode] 18. 四数之和

    题目链接:https://leetcode-cn.com/problems/4sum/ 题目描述: 给定一个包含 n 个整数的数组 nums 和一个目标值 target,判断 nums 中是否存在四个 ...