zoukankan      html  css  js  c++  java
  • 所驼门王的宝藏(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;
    }
  • 相关阅读:
    上下文调用(call , apply , bind)
    源码学习第七天(水滴石穿)
    学习源码第六天(加油别放弃)
    学习源码第五天(难得可贵)
    学习源码第四天(昨天只看了一点正则,发现正则真的水很深,但很有魅力)
    简单谈谈$.merge()
    学习源码第三天(短暂的坚持)
    学习源码第二天(渐入佳境)
    jquery源码学习第一天
    经典面试题简单分析
  • 原文地址:https://www.cnblogs.com/harden/p/6601141.html
Copyright © 2011-2022 走看看