Codeforces 1733D 891C Envy+1681F Unique Occurrences(可撤销并查集)

891C Envy

题意

        给定一张图以及q个查询,输出每个查询中的边是否全部会出现在某个最小生成树里。

思路

        

首先如果只考虑一次查询,这一次查询只有一条边,那么只要用kruskal算法处理完所有边权小于这条边的边,此时如果这条边的两点已经在同一个连通块里了,那么这条边不可能在MST里,反之则一定可以在某一个MST里。

对于多次查询,每次查询多条边来说类似,先存下所有的询问,然后按照边从小到大开始遍历,如果一组询问中有一条边不符合,那么这个询问就是NO的。

用可撤销并查集来维护每次询问每种边权增加后还原的操作。

代码

#include <bits/stdc++.h>

using namespace std;
#define int unsigned long long
const int N = 5e5 + 100;
const int mod = 1000000007;
const int INF = 0x3f3f3f3f;

int n, m;
struct node {
    int u, v, w;
} a[N];

int fa[N], sz[N];
vector<pair<int &, int>> his_sz, his_fa;
map<int, vector<int>> mp[N];
vector<int> ve[N];
int ans[N];

int find(int x) {
    while (x != fa[x])
        x = fa[x];
    return fa[x];
}

void union_set(int x, int y) {
    x = find(x);
    y = find(y);
    if (x != y) {
        if (sz[x] < sz[y])
            swap(x, y);
        his_sz.emplace_back(sz[x], sz[x]);
        sz[x] += sz[y];
        his_fa.emplace_back(fa[y], fa[y]);
        fa[y] = x;
    }
}

int history() {
    return his_fa.size();
}

void roll(int h) {
    while (his_fa.size() > h) {
        his_fa.back().first = his_fa.back().second;
        his_fa.pop_back();
        his_sz.back().first = his_sz.back().second;
        his_sz.pop_back();
    }
}


void solve() {
    cin >> n >> m;
    for (int i = 1; i <= m; i++) {
        int u, v, w;
        cin >> u >> v >> w;
        a[i].u=u;
        a[i].v=v;
        a[i].w=w;
        ve[w].push_back(i);
    }
    for(int i=1;i<=n;i++){
        fa[i]=i;
        sz[i]=1;
    }
    int q;
    cin >> q;
    for (int j = 1; j <= q; j++) {
        int k;
        cin >> k;
        for (int i = 1; i <= k; i++) {
            int idx;
            cin >> idx;
            mp[a[idx].w][j].push_back(idx);
        }
    }
    for (int w = 1; w <= 500010; w++) {
        if (ve[w].empty())continue;
        for (auto x: mp[w]) {
            if (ans[x.first] == 1)continue;
            int h = history();
            for (int y: x.second) {
                if (find(a[y].u) == find(a[y].v))ans[x.first] = 1;
                union_set(a[y].u, a[y].v);
            }
            roll(h);
        }
        for (auto x: ve[w]) {
            union_set(a[x].u, a[x].v);
        }
    }
    for (int i = 1; i <= q; i++) {
        if(ans[i]==1)cout<<"NO"<<'\n';
        else cout<<"YES"<<'\n';
    }
}

signed main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    int t = 1;
//	cin>>t;
    while (t--) solve();

    return 0;
}

Unique Occurrences

题意

给定一课带边权的树,对于一条从u到v的简单路径, f(u,v) 表示路径上只出现一次的边权的数量,输出所有 f(u,v) 的和。

思路

对于所有边权为 w 的边,它们对于答案的贡献就是只经过一次边权为 w 的路径的数量。因此可以把树中所有边权为 w 的边删除,剩余了一些连通块,这些连通块内没有边权为 w 的边,连通块之间原本是有一条边权为 w 的边,这样就比较容易计算了, w 对于答案的贡献就是所有连通块的大小两两相乘的和。

实现用简单的分治完成

代码

#include <bits/stdc++.h>

using namespace std;
#define int unsigned long long
const int N = 5e5 + 100;
const int mod = 1000000007;
const int INF = 0x3f3f3f3f;

vector<pair<int,int>>to[N];

int fa[N], sz[N];
vector<pair<int &, int>> his_sz, his_fa;


int find(int x) {
    while (x != fa[x])
        x = fa[x];
    return fa[x];
}

void union_set(int x, int y) {
    x = find(x);
    y = find(y);
    if (x != y) {
        if (sz[x] < sz[y])
            swap(x, y);
        his_sz.emplace_back(sz[x], sz[x]);
        sz[x] += sz[y];
        his_fa.emplace_back(fa[y], fa[y]);
        fa[y] = x;
    }
}

int history() {
    return his_fa.size();
}

void roll(int h) {
    while (his_fa.size() > h) {
        his_fa.back().first = his_fa.back().second;
        his_fa.pop_back();
        his_sz.back().first = his_sz.back().second;
        his_sz.pop_back();
    }
}

int dfs(int l,int r){
    if(l==r){
        int res=0;
        for(auto p:to[l]){
            res+=sz[find(p.first)]*sz[find(p.second)];
        }
        return res;
    }
    int res=0;
    int mid=(l+r)/2;
    int h=history();
    for(int i=l;i<=mid;i++){
        for(auto p:to[i]){
            union_set(p.first,p.second);
        }
    }
    res+=dfs(mid+1,r);
    roll(h);


    h=history();
    for(int i=mid+1;i<=r;i++){
        for(auto p:to[i]){
            union_set(p.first,p.second);
        }
    }
    res+=dfs(l,mid);
    roll(h);
    
    return res;
}


void solve(){
    int n;
    cin>>n;
    for(int i=1;i<=n;i++){
        fa[i]=i;
        sz[i]=1;
        if(i==n)continue;
        int u,v,w;
        cin>>u>>v>>w;
        to[w].emplace_back(u,v);
    }
    cout<<dfs(1,n);
}

signed main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    int t = 1;
//	cin>>t;
    while (t--) solve();

    return 0;
}

这个错误是由于无法连接到本地主机的10248端口导致的。这个端口通常是kubelet进程监听的端口,用于健康检查。出现这个错误可能是由于kubelet进程没有正确启动或者配置错误导致的。 解决这个问题的方法是检查kubelet进程的状态和配置。你可以按照以下步骤进行操作: 1. 检查kubelet进程是否正在运行。你可以使用以下命令检查kubelet进程的状态: ```shell systemctl status kubelet ``` 如果kubelet进程没有运行,你可以使用以下命令启动它: ```shell systemctl start kubelet ``` 2. 检查kubelet的配置文件。你可以使用以下命令查看kubelet的配置文件路径: ```shell kubelet --kubeconfig /etc/kubernetes/kubelet.conf --config /var/lib/kubelet/config.yaml --bootstrap-kubeconfig /etc/kubernetes/bootstrap-kubelet.conf config view ``` 确保配置文件中的端口号和地址正确,并且与你的环境相匹配。 3. 检查网络连接。你可以使用以下命令检查是否可以连接到localhost10248端口: ```shell curl -sSL http://localhost:10248/healthz ``` 如果无法连接,请确保端口没有被防火墙或其他网络配置阻止。 4. 检查docker的配置。有时候,kubelet进程依赖于docker进程。你可以按照以下步骤检查docker的配置: - 创建/etc/docker目录: ```shell sudo mkdir /etc/docker ``` - 编辑/etc/docker/daemon.json文件,并添加以下内容: ```json { "exec-opts": ["native.cgroupdriver=systemd"], "log-driver": "json-file", "log-opts": { "max-size": "100m" }, "storage-driver": "overlay2", "storage-opts": [ "overlay2.override_kernel_check=true" ], "registry-mirrors": ["https://tdhp06eh.mirror.aliyuncs.com"] } ``` - 重启docker进程: ```shell systemctl restart docker ``` 请注意,以上步骤是一种常见的解决方法,但具体解决方法可能因环境而异。如果以上步骤无法解决问题,请提供更多的错误信息和环境配置,以便我们能够更好地帮助你。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

心刍

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值