bzoj4484[Jsoi2015]最小表示 拓补排序+bitset

来源:互联网 发布:管材销售 知乎 编辑:程序博客网 时间:2024/05/16 11:17

挺显然的吧,一条边没有影响当且仅当这个边相连的两个点已经可以互相到达,就是没想到用bitset维护,老纠结map。。。

#include<cstdio>#include<algorithm>#include<cstring>#include<bitset>#include<queue>#define fo(i,a,b) for(int i=a;i<=b;i++)#define fd(i,a,b) for(int i=a;i>=b;i--)using namespace std;const int N=3e4+5;int n,m;bitset<N> f[N];queue<int>q;int d[N],a[N],tot;int head[100005],go[100005],next[100005];inline void add(int x,int y){    go[++tot]=y;    next[tot]=head[x];    head[x]=tot;}inline void topsort(){    int a1=0;    fo(i,1,n)if (!d[i])q.push(i);    while (!q.empty())    {        int x=q.front();        q.pop();        a[++a1]=x;        for(int i=head[x];i;i=next[i])        {            int v=go[i];            d[v]--;            if (!d[v])q.push(v);        }    }}int main(){    scanf("%d%d",&n,&m);    fo(i,1,m)    {        int x,y;        scanf("%d%d",&x,&y);        add(x,y);        d[y]++;     }    topsort();    int ans=0;    fd(i,n,1)    {        int x=a[i];        for(int j=head[x];j;j=next[j])        {            int v=go[j];            f[x]|=f[v];        }        for(int j=head[x];j;j=next[j])        {            int v=go[j];            if (f[x][v])ans++;            f[x].set(v);        }    }    printf("%d\n",ans);}
原创粉丝点击