Codeforces Round #736 (Div. 2) C
思路
觉得做法很神奇,感觉不难,就是自己没想到,写个题解记录一下。
- 对于这道题,我们首先肯定的是,如果与一个点相连的另一个点,比它大,那么它一定会被删除,所以我们维护一下哪些点与比它大的点相连。我们记录这些点的入度,in[i]。
- 初始时,对于给出的边u,v(u>v) ,那么v一定会被删除,in[v]++,在这之前判断当in[v]=0时,ans- -(ans初始化n),因为你一个点只能删除一次嘛。
- 对于加边操作,1,u,v(u>v), 那么v一定会被删除,按照上面的方法再判断一下。
- 对于删边操作,2,u,v(u>v), 先in[v]- -, 如果in[v]=0了, 那么证明没有比它大的点与它相连,ans++
AC代码
#include<bits/stdc++.h>
using namespace std;
const int N = 2e5+9;
int in[N];
int main()
{
int n,m;
scanf("%d %d",&n,&m);
int ans=n;
for(int i=0; i<m; i++)
{
int u,v;
scanf("%d %d",&u,&v);
if(u<v) swap(u,v);
if(in[v]==0) ans--;
in[v]++;
}
int q;
scanf("%d",&q);
while(q--)
{
int op;
int u,v;
scanf("%d",&op);
if(op==3) printf("%d\n",ans);
else if(op==1)
{
scanf("%d %d",&u,&v);
if(u<v) swap(u,v);
if(in[v]==0) ans--;
in[v]++;
}
else
{
scanf("%d %d",&u,&v);
if(u<v) swap(u,v);
in[v]--;
if(in[v]==0) ans++;
}
}
return 0;
}
总结
这种套路的题见得少,一时间做不出来,所以思维题真的需要多积累,多锻炼。而且容易误导人想成并查集,但是仔细想并查集做不出来的