十分求调

P6121 [USACO16OPEN] Closing the Farm G

scc36 @ 2024-02-04 10:04:25

#include <bits/stdc++.h>
using namespace std;
int n,m,i,j,fl,s,b[1000001],a[1000001];
int fx,fy,e[1000001],f[1000001],ff[1000001],t,ss;
struct no{
    int x,y;
}x[1000001];
int fi(int t){
    if(f[t]==t) return t;
    else return f[t]=fi(f[t]);
}
bool cmp(no t,no w){  //排序
    if(b[t.x]<b[w.x]&&b[t.y]<b[w.y]) return 0;
    else if(b[t.x]>b[w.x]&&b[t.y]<b[w.y]) return 0;
    else if(b[t.x]<b[w.x]&&b[t.y]>b[w.y]) return 0;
    return 1;
}
int main(){
    ios::sync_with_stdio(0);
    cin.tie(0);cout.tie(0);
    cin>>n>>m;
    for(i=1;i<=n;i++) f[i]=i;
    for(i=1;i<=m;i++) cin>>x[i].x>>x[i].y;
    for(i=1;i<=n;i++) cin>>a[i],b[a[i]]=i;
    sort(x+1,x+m+1,cmp);
    t=1;
    for(i=n;i>=1;i--){
        e[a[i]]=1;ss++;   //连通块++
        while(e[x[t].x]==1&&e[x[t].y]==1&&t<=m){
            fx=fi(x[t].x),fy=fi(x[t].y);
            if(fx!=fy) ss--,f[fx]=fy;  //连通块--
            t++;
        }
        if(ss==1) b[i]=1;
        else b[i]=0;
    }
    for(i=1;i<=n;i++)
        if(b[i]) cout<<"YES\n";
        else cout<<"NO\n";
}

个人认为思想正确,但只有十分/(ㄒoㄒ)/~~
那位大佬来看看?


by Gambler_Super @ 2024-02-04 10:16:26

@scc36 不会


by ChampionCyan @ 2024-02-17 11:01:10

我这跟你一样,10pts

555……

#include <bits/stdc++.h>
using namespace std;
const int MAXN = 2e5 + 1;
vector<int> e[MAXN], q;
int fa[MAXN], op[MAXN];
bool isopen[MAXN] = {};
stack<bool> ans;

int find(int x) {
    return fa[x] == x ? x : fa[x] = find(fa[x]);
}

int main() {
    int n, m;
    scanf("%d%d", &n, &m);
    while (m--) {
        int a, b;
        scanf("%d%d", &a, &b);
        e[a].push_back(b), e[b].push_back(a);
    }
    for (int i = 1; i <= n; i++)
        fa[i] = i;
    printf("YES\n");
    for (int i = n - 1; i > 1; i--)
        scanf("%d", &op[i]);
    for (int i = 2; i < n; i++) {
        int open = op[i];
        isopen[open] = true, q.push_back(open);
        for (int edge : e[i]) {
            int fe = find(edge);
            for (int j = 1; j <= n; j++)
                if (find(j) == fe && j != edge)
                    fa[j] = open;
            fa[edge] = open;
        }
        int father = q[0];
        bool ok = true;
        for (int j = 1; j < (int)q.size(); j++)
            if (find(j) != father) {
                ok = false;
                break;
            }
        ans.push(ok);
    }
    while (!ans.empty()) {
        if (ans.top())
            printf("YES\n");
        else
            printf("NO\n");
        ans.pop();
    }
    printf("YES\n");
    return 0;
}

by junwei @ 2024-05-15 20:49:54

@weah964 你的错误和我的是一样的 scc36的代码我没看出啥

@weah964 把fe删掉 每次在循环里使用find函数 因为每次访问时,并查集一直在变化 fe的值并不是最新并查集的询问而是改变前并查集的询问


by ChampionCyan @ 2024-05-16 18:00:02

@junweili

具体点吧,代码咋改?蒟蒻真看不懂什么意思


by ChampionCyan @ 2024-05-16 18:07:35

@junweili

笑死-ing


by junwei @ 2024-05-16 22:28:23

@weah964 会改的吧 加油


by junwei @ 2024-05-16 22:36:47

nb我改了一下你的代码 其它都TLE了... 幸好你自己已经AC了


by ChampionCyan @ 2024-05-17 17:16:20

@junweili

我这个TLE正常,时间复杂度 O(n^2)

for (int i = 2; i < n; i++) {
        int open = op[i];
        isopen[open] = true, q.push_back(open);
        for (int edge : e[i]) {
            int fe = find(edge);
            for (int j = 1; j <= n; j++)
                if (find(j) == fe && j != edge)
                    fa[j] = open;
            fa[edge] = open;
        }
        int father = q[0];
        bool ok = true;
        for (int j = 1; j < (int)q.size(); j++)
            if (find(j) != father) {
                ok = false;
                break;
            }
        ans.push(ok);
    }

你看,两层循环,就是复杂度都超标了


by junwei @ 2024-05-17 20:26:49

nb 这是我的代码

// Problem: P6121 [USACO16OPEN] Closing the Farm G
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/P6121
// Memory Limit: 250 MB
// Time Limit: 2000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

#include <bits/stdc++.h>
using namespace std;

const int N = 4e5 + 10;
int h[N], e[N], ne[N], idx;
bool st[N];
int p[N], q[N];
int res[N];

void add(int a, int b)
{
    e[idx] = b, ne[idx] = h[a], h[a] = idx++;
}

int find(int x)
{
    if (p[x] != x) p[x] = find(p[x]);

    return p[x];
}

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);

    int n, m;
    cin >> n >> m;

    memset(h, -1, sizeof h);

    int a, b;
    while (m--)
    {
        cin >> a >> b;

        add(a, b);
        add(b, a);
    }

    for (int i = 1; i <= n; i++) p[i] = i;

    for (int i = 1; i <= n; i++)
    {
        cin >> q[i];

        st[q[i]] = true;
    }

    int cnt = 0;
    for (int i = n; i; i--)
    {   
        cnt++;

        for (int j = h[q[i]]; ~j; j = ne[j])
        {
            int k = e[j];

            a = find(q[i]), b = find(k);

            if (a != b && !st[k])
            {
                p[a] = b;
                cnt--;
            }
        }

        st[q[i]] = false;
        res[i] = cnt;
    }

    for (int i = 1; i <= n; i++)
        if (res[i] == 1) cout << "YES\n";
        else cout << "NO\n";

    return 0;
}

by junwei @ 2024-05-17 20:29:42

@weah964 你可以看一下 add函数是链式前项星


|