P6134 [JSOI2015]最小表示 题解
对于每一条边
那么接下来就要想办法对每条边判断是否存在点
接下来就是对
#include<bits/stdc++.h>
using namespace std;
inline void read(int &x)
{
x=0;bool t=false;char c=getchar();
while(c<'0'||c>'9')c=='-'?t=1:0,c=getchar();
while(c>='0'&&c<='9')x=x*10+(c&15),c=getchar();
t?x=-x:x;
}
const int N=3e4+10,M=1e5+10;
vector<int>e[N];
vector<int>back[N];
int in[N],u[M],v[M];
bitset<N>to[N],cm[N];//两个点集to和come
int tupo[N],cnt=0,n,m;
void topsort()
{
queue<int>q;
for(int i=1;i<=n;++i)
if(!in[i])
q.push(i);
while(!q.empty())
{
int x=q.front();
q.pop();
tupo[++cnt]=x;
for(int y:e[x])
{
in[y]--;
if(!in[y])
q.push(y);
}
}
}
int main()
{
read(n);read(m);
for(int i=1;i<=m;++i)
{
read(u[i]);read(v[i]);
e[u[i]].push_back(v[i]);
back[v[i]].push_back(u[i]);
in[v[i]]++;
}
topsort();
for(int i=n;i;--i)
{
int x=tupo[i];
for(int y:e[x])
{
to[x][y]=1;
to[x]|=to[y];
}
}
for(int i=1;i<=n;++i)
{
int x=tupo[i];
for(int y:back[x])
{
cm[x][y]=1;
cm[x]|=cm[y];
}
}
int ans=0;
for(int i=1;i<=m;++i)
if((to[u[i]]&cm[v[i]])!=0)
ans++;
printf("%d",ans);
return 0;
}