b_lg_关闭农场 & 朋友(读题+反向思维并查集)

关闭农场

FJ 现在正感兴趣于知道在每一个时间(这里的“时间”指在每一次关闭谷仓之前的时间)时他的农场是否是“全连通的”

思路
这题正向做超时了,正解是倒着想(参考别人的思路),从后往前枚举并依次设置每个农场的状态为开启

#include<bits/stdc++.h>
using namespace std;
const int N=2e5+5;
vector<int> g[N];
int a[N], sz[N], fa[N], ans[N], is_open[N];
int find(int u) {
    return fa[u]==u ? u : fa[u]=find(fa[u]);
}
void merge(int u, int v) {
    int fu=find(u), fv=find(v);
    if (fu!=fv) {
        fa[fv]=fu;
        sz[fu]+=sz[fv];
    }
}
int main() {
    std::ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
    int n,m, u,v; cin>>n>>m;
    for (int i=0; i<m; i++) cin>>u>>v, g[u].push_back(v), g[v].push_back(u);
    for (int i=1; i<=n; i++) cin>>a[i], fa[i]=i, sz[i]=1;
    
    for (int i=n; i>=1; i--) {
        int u=a[i]; is_open[u]=1;
        for (int v : g[u]) if (is_open[v])
            merge(u,v);
        if (sz[find(u)]==n-i+1) ans[i]=1; //如果不等,则证明连通块中的点在图中并不是两两连续的
    }
    for (int i=1; i<=n; i++) cout<<(ans[i] ? "YES" : "NO")<<'\n';
    return 0;
}

朋友

A公司有N名员工,其中有P对朋友关系。B公司有M名员工,其中有Q对朋友关系。朋友的朋友一定还是朋友。
男人的编号是正数,女人的编号是负数。小明的编号是1,小红的编号是-1.
求通过小明和小红认识的人最多一共能配成多少对情侣。(包括他们自己)

思路
点睛之笔是通过小明和小红认识的人xxxx

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+5;
int fa[N];
int find(int u) {
    return fa[u]==u ? u : fa[u]=find(fa[u]);
}
void merge(int u, int v) {
    int fu=find(u), fv=find(v);
    if (fu!=fv)
        fa[fu]=fv;
}
int main() {
    std::ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
    int n,m, p,q, u,v, c1=0,c2=0; cin>>n>>m>>p>>q;
    for (int i=1; i<=n+m; i++) fa[i]=i;
    for (int i=0; i<p; i++) cin>>u>>v, merge(u,v);
    for (int i=0; i<q; i++) cin>>u>>v, u=u*-1+n, v=v*-1+n, merge(u,v);
    for (int i=1; i<=n; i++) if (find(i)==find(1)) c1++;
    for (int i=n+1; i<=n+m+1; i++) if (find(i)==find(n+1)) c2++;
    cout<<min(c1,c2);
    return 0;
}
posted @ 2020-10-09 11:40  童年の波鞋  阅读(87)  评论(0编辑  收藏  举报