疫情防控L3
思考:
首先题意说给n点m边,然后k条处理每次删去一个点,然后再给你一些点对,看看是否能互相到达。明显能看出是找出点是否在一个连通块或者集合里面,如果dfs就标记,被删掉的点不能走,很简单,但是这样时间复杂度很大。另一个就会想到并查集,但是仅仅会简单的去想删边并查集也不能操作啊,记住以后只要想删边,那就去想离线倒叙并查集。每次处理最后的,然后再把点边补上,这是很好的复杂度。
结论:
直接dfs标记类简单但是复杂度高,倒叙并查集是个好的选择。
代码:
int T,n,m,k;
int va[N];
int vis[N];
int acc[N];
vector<int > e[N],re,anw;
vector<PII > v[N];
int find(int x);
signed main()
{
IOS;
cin>>n>>m>>k;
for(int i=1;i<=n;i++) acc[i] = i;
for(int i=1;i<=m;i++)
{
int a,b;
cin>>a>>b;
e[a].pb(b);
e[b].pb(a);
}
for(int i=1;i<=k;i++)
{
int A,x;
cin>>A>>x;
re.pb(A);
vis[A] = 1;
for(int j=1;j<=x;j++)
{
int a,b;
cin>>a>>b;
v[i].pb({a,b});
}
}
for(int now=1;now<=n;now++)
{
for(auto spot:e[now])
{
if(vis[spot]||vis[now]) continue;
int t1 = find(now),t2 = find(spot);
if(t1!=t2) acc[t1] = t2;
}
}
for(int i=k;i>=1;i--)
{
int ans = 0;
for(auto t:v[i])
{
int t1 = find(t.fi),t2 = find(t.se);
if(t1!=t2||vis[t.fi]||vis[t.se]) ans++;
}
int now = re[i-1];
vis[now] = 0;
for(auto spot:e[now])
{
int t1 = find(now),t2 = find(spot);
if(t1!=t2) acc[t1] = t2;
}
anw.pb(ans);
}
for(int i=anw.size()-1;i>=0;i--) cout<<anw[i]<<"\n";
return 0;
}
int find(int x)
{
if(x!=acc[x]) acc[x] = find(acc[x]);
return acc[x];
}
总结:
总言而止呢,比赛不要太紧张,思考一些傻逼性的问题是没有结果的,要冷静下来去分析如何去解决它。
卡空间:
#include
#define fi first
#define se second
#define pb push_back
#define db double
#define ll long long
#define PII pair<int,int >
#define mem(a,b) memset(a,b,sizeof(a))
#define IOS std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
using namespace std;
const int mod = 1e9+7,inf = 1e9;
const int N = 5e4+10,M = 2e6+10,K = 2e5+10;
int T,n,m,k;
PII va[N];
int vb[N];
int vis[N];
int acc[N];
int anw[N];
int h[K],e[K],ne[K],idx;
int h1[M],e1[M],e2[M],ne1[M],idx1;
void add(int a,int b)
{
e[idx] = b;
ne[idx] = h[a];
h[a] = idx++;
}
void add1(int a,int b,int c)
{
e1[idx1] = b;
e2[idx1] = c;
ne1[idx1] = h1[a];
h1[a] = idx1++;
}
int find(int x)
{
if(x!=acc[x]) acc[x] = find(acc[x]);
return acc[x];
}
signed main()
{
IOS;
cin>>n>>m>>k;
mem(h,-1);mem(h1,-1);
for(int i=1;i<=n;i++) acc[i] = i;
for(int i=1;i<=m;i++)
{
int a,b;
cin>>a>>b;
va[i] = {a,b};
add(a,b);add(b,a);
}
for(int i=1;i<=k;i++)
{
int x;
cin>>vb[i]>>x;
vis[vb[i]] = 1;
while(x--)
{
int a,b;
cin>>a>>b;
add1(i,a,b);
}
}
for(int i=1;i<=m;i++)
{
int a = va[i].fi,b = va[i].se;
if(vis[a]||vis[b]) continue;
acc[find(a)] = find(b);
}
for(int i=k;i>=1;i--)
{
for(int j=h1[i];j!=-1;j=ne1[j])
{
int a = e1[j],b = e2[j];
if(vis[a]||vis[b]||find(a)!=find(b)) anw[i]++;
}
vis[vb[i]] = 0;
for(int j=h[vb[i]];j!=-1;j=ne[j])
{
int a = vb[i],b = e[j];
acc[find(b)] = find(a);
}
}
for(int i=1;i<=k;i++) cout<<anw[i]<<"\n";
return 0;
}