所驼门王的宝藏(bzoj 1924)

Description

Input

第一行给出三个正整数 N, R, C。 以下 N 行,每行给出一扇传送门的信息,包含三个正整数xi, yi, Ti,表示该传送门设在位于第 xi行第yi列的藏宝宫室,类型为 Ti。Ti是一个1~3间的整数, 1表示可以传送到第 xi行任意一列的“横天门”,2表示可以传送到任意一行第 yi列的“纵寰门”,3表示可以传送到周围 8格宫室的“自 由门”。 保证 1≤xi≤R,1≤yi≤C,所有的传送门位置互不相同。

Output

只有一个正整数,表示你确定的路线所经过不同藏宝宫室的最大数目。

Sample Input

10 7 7
2 2 1
2 4 2
1 7 2
2 7 3
4 2 2
4 4 1
6 7 3
7 7 1
7 5 2
5 2 1

Sample Output

9

HINT

测试点编号 N R C 1 16 20 20 2 300 1,000 1,000 3 500 100,000 100,000 4 2,500 5,000 5,000 5 50,000 5,000 5,000 6 50,000 1,000,000 1,000,000 7 80,000 1,000,000 1,000,000 8 100,000 1,000,000 1,000,000 9 100,000 1,000,000 1,000,000 10 100,000 1,000,000 1,000,000

/*
    按照题目要求建图,缩点跑最长路。 
*/ 
#include<cstdio>
#include<iostream>
#include<vector>
#include<map>
#define N 100010
#define M 1000010
using namespace std;
int x[N],y[N],t[N],K,n,m;
int head1[N],head2[N],cnt;
int low[N],dfn[N],sta[N],ins[N],bl[N],num[N],indexx,top,scc;
int dep[N],vis[N],ans;
int dx[8]={0,0,1,1,1,-1,-1,-1};
int dy[8]={1,-1,0,1,-1,0,1,-1};
struct node{int v,pre;}e1[M],e2[M];
vector<int> a[M],b[M];
map<int,int> mp[M];
void add1(int u,int v){
    if(u==v) return;
    e1[++cnt].v=v;e1[cnt].pre=head1[u];head1[u]=cnt;
}
void add2(int u,int v){
    e2[++cnt].v=v;e2[cnt].pre=head2[u];head2[u]=cnt;
}
void build(){
    for(int i=1;i<=n;i++){
        int x=0;
        for(int j=0;j<a[i].size();j++)
            if(t[a[i][j]]==1) {x=a[i][j];break;}
        for(int j=0;j<a[i].size();j++){
            add1(x,a[i][j]);
            if(t[a[i][j]]==1) add1(a[i][j],x);
        }
    }
    for(int i=1;i<=m;i++){
        int x=0;
        for(int j=0;j<b[i].size();j++)
            if(t[b[i][j]]==2) {x=b[i][j];break;}
        for(int j=0;j<b[i].size();j++){
            add1(x,b[i][j]);
            if(t[b[i][j]]==2) add1(b[i][j],x);
        }
    }
    for(int i=1;i<=K;i++)
        if(t[i]==3)
            for(int j=0;j<8;j++){
                int t=mp[x[i]+dx[j]][y[i]+dy[j]];
                if(t) add1(i,t);
            }
}
void tarjan(int u){
    dfn[u]=low[u]=++indexx;
    sta[++top]=u;ins[u]=1;
    for(int i=head1[u];i;i=e1[i].pre)
        if(!dfn[e1[i].v]){
            tarjan(e1[i].v);
            low[u]=min(low[u],low[e1[i].v]);
        }
        else if(ins[e1[i].v])
            low[u]=min(low[u],dfn[e1[i].v]);
    int x;
    if(low[u]==dfn[u]){
        ++scc;
        do {
            x=sta[top--];
            ins[x]=0;
            bl[x]=scc;
            num[scc]++;
        }while(u!=x);
    }
}
void rebuild(){
    cnt=0;
    for(int i=1;i<=K;i++)
        for(int j=head1[i];j;j=e1[j].pre)
            if(bl[i]!=bl[e1[j].v])
                add2(bl[i],bl[e1[j].v]);
}
void dfs(int x){
    vis[x]=1;
    for(int i=head2[x];i;i=e2[i].pre){
        if(!vis[e2[i].v]) dfs(e2[i].v);
        dep[x]=max(dep[x],dep[e2[i].v]);
    }
    dep[x]+=num[x];
    ans=max(ans,dep[x]);
}
int main(){
    scanf("%d%d%d",&K,&n,&m);
    for(int i=1;i<=K;i++){
        scanf("%d%d%d",&x[i],&y[i],&t[i]);
        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<=scc;i++)
        if(!vis[i]) dfs(i);
    printf("%d",ans);
    return 0;
}

 

posted @ 2017-03-22 17:43  karles~  阅读(329)  评论(0编辑  收藏  举报