【Luogu】P2403所驼门王的宝藏(强连通分量)

  题目链接

  想到缩点后DP这题就迷之好做

  横天门就点向该行连一条边

  纵门就点向该列连一条边

  ziyou门直接枚举……map搞搞……话说ziyou门为啥是违规内容不让我发布?

  然后缩点,DP,1A

  不过写得迷之心累……想装死……

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cctype>
#include<cstdlib>
#include<map>
#define maxn 2200010
#define maxd 100020
#define base r+c
using namespace std;
inline long long read(){
    long long num=0,f=1;
    char ch=getchar();
    while(!isdigit(ch)){
        if(ch=='-')    f=-1;
        ch=getchar();
    }
    while(isdigit(ch)){
        num=num*10+ch-'0';
        ch=getchar();
    }
    return num*f;
}

int dfn[maxn],cnt;
int stack[maxn],top;
int col[maxn],ID;
bool vis[maxn];
int low[maxn];
int size[maxn],sum[maxn];
bool ext[maxn];
int n,r,c;

int ans;

struct Pic{
    struct Edge{
        int next,to;
    }edge[maxn*2];
    int head[maxn],num;
    Pic(){memset(head,0,sizeof(head));}
    inline void add(int from,int to){
        edge[++num]=(Edge){head[from],to};
        head[from]=num;
    }
    void tarjan(int x){
        //printf("%d\n",x);
        dfn[x]=low[x]=++cnt;
        vis[x]=1;    stack[++top]=x;
        for(int i=head[x];i;i=edge[i].next){
            int to=edge[i].to;
            if(dfn[to]==0){
                tarjan(to);
                low[x]=min(low[x],low[to]);
            }
            else if(vis[to])    low[x]=min(low[x],dfn[to]);
        }
        if(low[x]==dfn[x]){
            col[x]=++ID;    vis[x]=0;
            if(x>base)    size[ID]++;
            while(stack[top]!=x){
                col[stack[top]]=ID;
                vis[stack[top]]=0;
                if(stack[top]>base)    size[ID]++;
                top--;
            }
            top--;
        }
    }
    void dfs(int x){
        vis[x]=1;
        for(int i=head[x];i;i=edge[i].next){
            int to=edge[i].to;
            if(vis[to]){
                sum[x]=max(sum[x],sum[to]);
                continue;
            }
            dfs(to);
            sum[x]=max(sum[x],sum[to]);
        }
        sum[x]+=size[x];
        ans=max(ans,sum[x]);
        return;
    }
}Old,New;

map<long long,int>d;


inline long long calc(long long i,long long j){    return (i-1)*c+j+base;    }

struct Node{
    int x,y,id,opt;
}q[maxd];

int u[9]={0,-1,-1,0,1,1,1,0,-1};
int w[9]={0,0,1,1,1,0,-1,-1,-1};

int main(){
    n=read(),r=read(),c=read();
    for(int i=1;i<=n;++i){
        int x=read(),y=read(),opt=read();
        long long now=calc(x,y);
        ext[x]=ext[y+r]=ext[i+base]=1;
        Old.add(x,i+base);
        Old.add(y+r,i+base);
        q[i]=(Node){x,y,i+base,opt};
        d[now]=i+base;
    }
    for(int i=1;i<=n;++i){
        int opt=q[i].opt;
        if(opt==1)        Old.add(q[i].id,q[i].x);
        else if(opt==2)    Old.add(q[i].id,q[i].y+r);
        else{
            for(int j=1;j<9;++j){
                int x=q[i].x+u[j],y=q[i].y+w[j];
                if(x<1||x>r||y<1||y>c)    continue;
                if(d.count(calc(x,y)))    Old.add(q[i].id,d[calc(x,y)]);
            }
        }
    }
    for(int i=1;i<=n+base;++i)
        if(ext[i]&&dfn[i]==0)    Old.tarjan(i);
    for(int i=1;i<=n+base;++i)
        for(int j=Old.head[i];j;j=Old.edge[j].next){
            int to=Old.edge[j].to;
            if(col[i]==col[to])    continue;
            New.add(col[i],col[to]);
        }
    for(int i=1;i<=ID;++i)
        if(vis[i]==0)    New.dfs(i);
    printf("%d\n",ans);
    return 0;
}

 

posted @ 2018-04-17 10:23  Konoset  阅读(180)  评论(0编辑  收藏  举报