P6134 [JSOI2015]最小表示
luckydrawbox · · 题解
题意
给定一个有向无环图,节点编号为
分析
先分析一下样例:
由样例解释得,边
所以,一条边
设边集为
设
我们对图进行拓补排序,遍历每条边
这样做的时间复杂度是
代码
#include<bits/stdc++.h>
#define ll long long
using namespace std;
long long read(){
long long x=0,f=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-') f=-1;ch=getchar();}
while(isdigit(ch)){x=x*10+ch-48;ch=getchar();}
return x*f;
}
void write(long long x){
if(x<0) putchar('-'),x=-x;
if(x>9) write(x/10);
putchar(x%10+'0');
}
const int N=3e4+10;
int n,m,in[N],ans;
vector<int>e[N];
bitset<N>d[N],w[N];
void topu(){
queue<int>q;
for(int i=1;i<=n;i++)
if(!in[i])
q.push(i);
while(q.size()){
int x=q.front();q.pop();
for(int i=0,y;i<e[x].size();i++){
in[y=e[x][i]]--;
d[y]|=d[x]|w[x];
if(!in[y])
q.push(y);
}
}
}
int main(){
n=read();m=read();
for(int i=1,x,y;i<=m;i++){
x=read();y=read();
e[x].push_back(y);
in[y]++;
w[y][x]=1;
}
topu();
for(int i=1;i<=n;i++)
for(int j=0;j<e[i].size();j++)
ans+=d[e[i][j]][i];
write(ans);
return 0;
}