zoukankan      html  css  js  c++  java
  • [题解] [CF891C] Envy

    题面

    题解

    对于同一个图中的最小生成树, 有如下性质

    1. 对于不同最小生成树中同一权值的边的数量是一定的, 可通过反证法证明, 在这里就不证了
    2. 对于任意正确加边方案, 加完小于某权值的边后连通性是一样的

    所以根据以上性质, 可以判断某一权值能否在一棵最小生成树中同时出现, 具体方法如下

    在Kruscal的过程中, 当把小于某一权值的所有边都处理完后, 对于这一权值的所有边, 记录下每条边两个端点所在的联通块

    然后对于每组询问, 将边的权值排序后对于每一种权值单独考虑(每一种权值互不影响, 自己思考一下为什么), 看这些边形成的联通块中是否有环, 并查集判断即可, 至于撤销并查集, 暴力撤销即可

    Code

    #include <algorithm>
    #include <iostream>
    #include <cstring>
    #include <cstdlib>
    #include <cstdio>
    #include <vector>
    #define itn int
    #define reaD read
    #define N 500005
    using namespace std;
    
    int n, m, fa[N]; 
    struct edge { int from, to, cost, ancf, anct, id; } e[N]; 
    struct Edge { int u, v, w; bool operator < (const Edge &p) const { return w < p.w; } }; 
    vector <Edge> vec; 
    
    inline int read()
    {
    	int x = 0, w = 1; char c = getchar();
    	while(c < '0' || c > '9') { if (c == '-') w = -1; c = getchar(); }
    	while(c >= '0' && c <= '9') { x = x * 10 + c - '0'; c = getchar(); }
    	return x * w;
    }
    
    bool cmp1(edge x, edge y) { return x.cost < y.cost; }
    
    bool cmp2(edge x, edge y) { return x.id < y.id; }
    
    int find(int x) { return fa[x] == x ? x : fa[x] = find(fa[x]); }
    
    void merge(int u, int v) { u = find(u), v = find(v); fa[u] = v; }
    
    int main()
    {
    	n = read(); m = read(); 
    	for(int i = 1; i <= n; i++) fa[i] = i; 
    	for(int i = 1; i <= m; i++) e[i].from = read(), e[i].to = read(), e[i].cost = read(), e[i].id = i; 
    	sort(e + 1, e + m + 1, cmp1); 
    	for(int i = 1; i <= m; )
    	{
    		int pos = i;
    		do
    		{
    			e[pos].ancf = find(e[pos].from);
    			e[pos].anct = find(e[pos].to); 
    			pos++; 
    		}
    		while(pos <= m && e[pos].cost == e[pos - 1].cost);
    		while(i < pos)
    		{
    			if(find(e[i].from) == find(e[i].to)) i++;
    			else merge(e[i].from, e[i].to), i++; 
    		}
    	}
    	for(int i = 1; i <= n; i++) fa[i] = i; 
    	sort(e + 1, e + m + 1, cmp2); 
    	int Q = read();
    	while(Q--)
    	{
    		int k = read(); vec.clear(); 
    		for(int i = 1; i <= k; i++)
    		{
    			int id = read(); 
    			vec.push_back((Edge) { e[id].ancf, e[id].anct, e[id].cost }); 
    		}
    		sort(vec.begin(), vec.end());
    		bool flag = 1; 
    		for(int i = 0; i < vec.size(); )
    		{
    			if(!flag) break; 
    			if(vec[i].u == vec[i].v) { flag = 0; break; };
    			merge(vec[i].u, vec[i].v); 
    			int pos = i + 1;
    			while(pos < vec.size() && vec[pos].w == vec[i].w)
    			{
    				if(find(vec[pos].u) == find(vec[pos].v)) { flag = 0; break; }
    				merge(vec[pos].u, vec[pos].v); pos++; 
    			}
    			while(i < pos) { fa[vec[i].u] = vec[i].u; fa[vec[i].v] = vec[i].v; i++; }
    		}
    		puts(flag ? "YES" : "NO"); 
    	}
    	return 0;
    } 
    
  • 相关阅读:
    Can't connect to local MySQL server through socket '/tmp/mysql.sock' (2)
    mac 上面安装mysql-python
    NSConditionLock
    NSCondition
    web.py 学习(二)Worker
    web.py 学习(-)Rocket web框架
    ARC 下面可能导致的内存问题
    WireShark 抓取Telnet包
    node.js里npm install --save 与 npm install --save-dev 的区别
    最近阅读链接
  • 原文地址:https://www.cnblogs.com/ztlztl/p/11182076.html
Copyright © 2011-2022 走看看