【玄关】思路感觉大体没问题 但是样例过不了

P1197 [JSOI2008] 星球大战

Bei_Gua_ @ 2024-11-04 21:05:55

思路大概就是假设所有应该被摧毁的城市全部被摧毁,统计存活的城市的联通块,然后从后往前每次依次连接所有关于本次被摧毁城市的边。

但是样例都过不了

Code:

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=4e5+5;
int n,m,k,ans;
vector<int>g[N];
map<int,bool>vis;
int pre[N],broke[N],res[N];
int root(int x){
    return pre[x]=(pre[x]==x?x:root(pre[x]));
}
void merge(int u,int v){
    int ru=root(u),rv=root(v);
    if (ru!=rv){
        ans++;
        pre[ru]=rv;
    }
}
bool isCon(int u,int v){
    return root(u)==root(v);
}
signed main(){
    ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
    cin>>n>>m;
    for (int i=0;i<n;i++)pre[i]=i;
    for (int i=1;i<=m;i++){
        int u,v;
        cin>>u>>v;
        g[u].push_back(v);
        g[v].push_back(u);
    }
    cin>>k;
    for (int i=1;i<=k;i++){
        cin>>broke[i];
        vis[broke[i]]=1;
    }
    for (int i=0;i<n;i++){
        if (g[i].size()&&!vis[i]){
            for (const auto &j:g[i]){
                if (!vis[j]){
                    merge(i,j);
                }
            }
        }
    }
    res[k+1]=n-k-ans;
    ans=0;
    for (int i=k;i>=1;i--){
        for (const auto &j:g[broke[i]]){
            if (!j){
                merge(broke[i],j);
            }
        }
        cout<<ans<<"\n";
        res[i]=res[k+1]-ans+1;
        vis[broke[i]]=0;
        ans=0;
    }
    for (int i=1;i<=k+1;i++)cout<<res[i]<<"\n";
}

|