zoukankan      html  css  js  c++  java
  • CF891C Envy

    题面

    题解

    首先要知道两个性质:

    1. 对于任意权值,最小生成树上该权值的边数是相同的。
    2. 对于任意一个最小生成树,当加完所有权值小于一个任意值的边之后,当前图的连通性是一样的。

    于是我们按照权值分开处理,对每一种边的权值的每一个询问都处理一遍即可,这个可以写一个到撤销操作的并查集。

    于是这道题目就做完了。

    代码

    #include<cstdio>
    #include<cstring>
    #include<cctype>
    #include<algorithm>
    #include<vector>
    #define RG register
    #define file(x) freopen(#x".in", "r", stdin), freopen(#x".out", "w", stdout)
    #define clear(x, y) memset(x, y, sizeof(x))
    
    inline int read()
    {
    	int data = 0, w = 1; char ch = getchar();
    	while(ch != '-' && (!isdigit(ch))) ch = getchar();
    	if(ch == '-') w = -1, ch = getchar();
    	while(isdigit(ch)) data = data * 10 + (ch ^ 48), ch = getchar();
    	return data * w;
    }
    
    const int maxn(5e5 + 10);
    struct edge { int x, y, w; } e[maxn];
    struct qry { int id, x, y, w; };
    inline int cmp(const edge &lhs, const edge &rhs) { return lhs.w < rhs.w; }
    std::vector<qry> Q[maxn];
    int fa[maxn], size[maxn], ans[maxn], n, m, q, stk[maxn], top;
    int find(int x) { return fa[x] == x ? x : find(fa[x]); }
    inline int merge(int x, int y)
    {
    	x = find(x), y = find(y);
    	if(x == y) return 0;
    	if(size[x] > size[y]) std::swap(x, y);
    	fa[x] = y, size[y] += size[x], stk[++top] = x;
    	return 1;
    }
    
    int main()
    {
    	n = read(), m = read();
    	for(RG int i = 1; i <= m; i++)
    		e[i] = (edge) {read(), read(), read()};
    	q = read();
    	for(RG int i = 1, k; i <= q; i++)
    	{
    		k = read();
    		for(RG int j = 1, x; j <= k; j++)
    			x = read(), Q[e[x].w].push_back((qry) {i, e[x].x, e[x].y, e[x].w});
    	}
    	std::sort(e + 1, e + m + 1, cmp);
    	for(RG int i = 1; i <= n; i++) size[fa[i] = i] = 1;
    	for(RG int i = 1; i <= q; i++) ans[i] = 1;
    	for(RG int i = 1; i <= m; i++)
    	{
    		int val = e[i].w; top = 0;
    		for(RG int j = 0; j < (int)Q[val].size(); j++)
    		{
    			if(!ans[Q[val][j].id]) continue;
    			if(j > 0 && Q[val][j].id != Q[val][j - 1].id)
    				while(top)
    				{
    					int x = stk[top--];
    					size[fa[x]] -= size[x];
    					fa[x] = x;
    				}
    			if(!merge(Q[val][j].x, Q[val][j].y))
    				ans[Q[val][j].id] = 0;
    		}
    		while(e[i].w == val) merge(e[i].x, e[i].y), ++i;
    		if(e[i].w != val) --i;
    	}
    	for(RG int i = 1; i <= q; i++) puts(ans[i] ? "YES" : "NO");
    	return 0;
    }
    
  • 相关阅读:
    Java中static、final、static final的区别(转)
    常见 重要知识精简总结
    面向对象编程三大特性------封装、继承、多态
    解决点击输入框调起键盘时,输入框被键盘遮挡的问题
    实用连接
    媒体查询兼容IE浏览器
    拖动到回收站删除
    vue2.0--组件通信
    图片上传
    上传图片预览
  • 原文地址:https://www.cnblogs.com/cj-xxz/p/10456493.html
Copyright © 2011-2022 走看看