bzoj1924: [Sdoi2010]所驼门王的宝藏

来源:互联网 发布:linux fm驱动 编辑:程序博客网 时间:2024/05/21 06:57

传送门
我们首先可以用O(NlogN)的时间建出来所有的边。
然后我们大力tarjan求联通块
之后大力拓扑排序一发就可以了。

#include<cstdio> #include<iostream>#include<cstdlib>#include<cmath>#include<cstring>#include<algorithm>#include<vector>#include<map>#define N 100005#define M 1000005using namespace std;const int xxx[8][2]={{-1,-1},{-1,0},{-1,1},{0,-1},{0,1},{1,-1},{1,0},{1,1}};int head[N],head2[N],x[N],y[N],z[N],co[N];int dfn[N],low[N],num[N],st[N],inq[N],mark[N],sum[N];vector<int> a[M],b[M];map<int,int> mp[M];struct edge{int to,next;}e[M],ed[M];int K,n,m,tot,top,color,tim,ans;inline int read(){    int x=0;    char ch=getchar();    for (;ch<'0'||ch>'9';ch=getchar());    for (;ch>='0'&&ch<='9';ch=getchar()) x=x*10-48+ch;    return x; }void ins(int x,int y){    if (x==y) return;    e[++tot].to=y;    e[tot].next=head[x];    head[x]=tot;}void ins2(int x,int y){    if (x==y) return;    ed[++tot].to=y;    ed[tot].next=head2[x];    head2[x]=tot;}void build(){    int p,t;    for (int i=1;i<=n;i++){        p=0;        t=a[i].size();        for (int j=0;j<t;j++)            if (z[a[i][j]]==1){p=a[i][j]; break;}        if (!p) continue;        for (int j=0;j<t;j++){            ins(p,a[i][j]);            if (z[a[i][j]]==1) ins(a[i][j],p);        }    }    for (int i=1;i<=m;i++){        p=0;        t=b[i].size();        for (int j=0;j<t;j++)            if (z[b[i][j]]==2){p=b[i][j]; break;}        if (!p) continue;        for (int j=0;j<t;j++){            ins(p,b[i][j]);            if (z[b[i][j]]==2) ins(b[i][j],p);        }    }    for (int i=1;i<=K;i++)        if (z[i]==3)            for (int j=0;j<8;j++){                t=mp[x[i]+xxx[j][0]][y[i]+xxx[j][1]];                if (t) ins(i,t);            }}void tarjan(int x){    dfn[x]=low[x]=++tim;    inq[x]=1;    st[++top]=x;    for (int i=head[x];i;i=e[i].next)        if (!dfn[e[i].to]){            tarjan(e[i].to);            low[x]=min(low[x],low[e[i].to]);        }        else if (inq[e[i].to])            low[x]=min(low[x],dfn[e[i].to]);    if (dfn[x]==low[x]){        int xx=0;        color++;        while (xx!=x){            xx=st[top--];            co[xx]=color;            inq[xx]=0;            num[color]++;        }    }}void rebuild(){    tot=0;    for (int i=1;i<=K;i++)        for (int j=head[i];j;j=e[j].next)            if (co[i]!=co[e[j].to]) ins2(co[i],co[e[j].to]);}void dp(int x){    mark[x]=1;    for (int i=head2[x];i;i=ed[i].next){        if (!mark[ed[i].to]) dp(ed[i].to);        sum[x]=max(sum[x],sum[ed[i].to]);    }    sum[x]+=num[x];    ans=max(ans,sum[x]);}int main(){    K=read(); n=read(); m=read();    for (int i=1;i<=K;i++){        x[i]=read();        y[i]=read();        z[i]=read();        mp[x[i]][y[i]]=i;        a[x[i]].push_back(i);        b[y[i]].push_back(i);    }    build();    for (int i=1;i<=K;i++)        if (!dfn[i]) tarjan(i);    rebuild();    for (int i=1;i<=color;i++)        if (!mark[i]) dp(i);    printf("%d",ans); }
原创粉丝点击