之前连bitset都不会写......为了写这道题去学习了一下bitset的用法
首先要得到一个很显然的结论,就是如果\(x\)和\(y\)之间的边可以被删去,那么\(x\)一定可以通过别的路径走到\(y\),然后在这里我们就需要用bitset来维护点与点之间的连通性
因为这是一个有向无环图,所以我们直接拓扑排序,然后从出度为零的点逆序入队,将每一个结点的子节点按照到出度为零的点的距离由大到小排序,可以保证最优,然后判一下\(bit[x][son]\)是不是1,如果是1就说明这条边是可以删掉的
#include<bits/stdc++.h>
using namespace std;
int n,m,x,y,r[30003],ru[30003],p,hd,st[30003],ans;
queue<int>q;
vector<int>l[30003];
bitset<30003>bit[30003];
int cmp(int nx,int ny)
{
return r[nx]>r[ny];
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++)
{
scanf("%d%d",&x,&y);
l[x].push_back(y),ru[y]++;
}
for(int i=1;i<=n;i++)
if(ru[i]==0)
q.push(i);
while(!q.empty())
{
p=q.front(),q.pop(),hd++,st[hd]=p;
for(int j=0;j<l[p].size();j++)
{
ru[l[p][j]]--;
if(ru[l[p][j]]==0)
q.push(l[p][j]);
}
}
for(int i=n;i>=1;i--)
{
x=st[i],bit[x][x]=1;
sort(l[x].begin(),l[x].end(),cmp);
for(int j=0;j<l[x].size();j++)
{
r[x]=max(r[l[x][j]]+1,r[x]);
if(bit[x][l[x][j]]==1)
ans++;
else
bit[x]|=bit[l[x][j]];
}
}
cout<<ans;
return 0;
}