zoukankan      html  css  js  c++  java
  • 【BZOJ-1924】所驼门王的宝藏 Tarjan缩点(+拓扑排序) + 拓扑图DP

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

    Time Limit: 5 Sec  Memory Limit: 128 MB
    Submit: 787  Solved: 318
    [Submit][Status][Discuss]

    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

    Source

    Solution

    题目并不难.

    很显然Tarjan缩点,重构图,然后在DAG上做DP,或者跑最长路

    麻烦的在于建图....

    需要用vector存在同一行上的格点,同一列上的格点,用map记录点的八连通,然后连边

    连边的方式有技巧,选一个横/竖格,对同行同列的所有点连单向边,对横/竖格连双向;八连通的直接连就好

    如果暴力连边,可能会出现一组WA的情况,可能需要再进行一遍拓扑排序

    Code

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<vector>
    #include<map>
    #include<algorithm>
    using namespace std;
    int read()
    {
        int x=0,f=1; char ch=getchar();
        while (ch<'0' || ch>'9') {if (ch=='-') f=-1; ch=getchar();}
        while (ch>='0' && ch<='9') {x=x*10+ch-'0'; ch=getchar();}
        return x*f;
    }
    #define maxn 100010
    int dx[8]={0,0,1,1,1,-1,-1,-1},dy[8]={1,-1,0,1,-1,0,1,-1};
    struct EdgeNode{int next,to;}edge[maxn*10],road[maxn*10];
    int cnt,tot,head[maxn],last[maxn];
    void addedge(int u,int v) {cnt++; edge[cnt].next=head[u]; head[u]=cnt; edge[cnt].to=v;}
    void insertedge(int u,int v) {if (u==v) return; addedge(u,v);}
    void addroad(int u,int v) {tot++; road[tot].next=last[u]; last[u]=tot; road[tot].to=v;}
    void insertroad(int u,int v) {addroad(u,v);}
    int x[maxn],y[maxn],t[maxn],dfn[maxn],low[maxn],stack[maxn],num[maxn],belong[maxn],dp[maxn];
    bool visit[maxn];
    int n,r,c,ans,top,qcnt;
    vector<int>h[maxn*10],l[maxn*10];
    map<int,int>mp[maxn*10];
    void BuildGraph()
    {
        for (int i=1; i<=r; i++) 
            {    
                int hn=h[i].size(),now=0;
                for (int j=0; j<=hn-1; j++) if (t[h[i][j]]==1) {now=h[i][j]; break;}
                for (int j=0; j<=hn-1; j++) {insertedge(now,h[i][j]); if (t[h[i][j]]==1) insertedge(h[i][j],now);}
            }
        for (int i=1; i<=c; i++)
            {
                int ln=l[i].size(),now=0;
                for (int j=0; j<=ln-1; j++) if (t[l[i][j]]==2) {now=l[i][j]; break;}
                for (int j=0; j<=ln-1; j++) {insertedge(now,l[i][j]); if (t[l[i][j]]==2) insertedge(l[i][j],now);}
            }
        for (int i=1; i<=n; i++)
            if (t[i]==3)
                for (int xx,yy,j=0; j<=7; j++)
                    {
                        xx=x[i]+dx[j],yy=y[i]+dy[j];
                        if (mp[xx][yy]) insertedge(i,mp[xx][yy]);
                    }
    }
    void Tarjan(int x) 
    { 
        dfn[x]=low[x]=++tot; visit[x]=1; stack[++top]=x; 
        for (int i=head[x]; i; i=edge[i].next) 
            { 
                if (!dfn[edge[i].to]) 
                    { 
                        Tarjan(edge[i].to); 
                        if (low[edge[i].to]<low[x]) low[x]=low[edge[i].to]; 
                    } 
                else 
                    if(visit[edge[i].to] && dfn[edge[i].to]<low[x]) 
                        low[x]=dfn[edge[i].to]; 
            }
        if (dfn[x]==low[x]) 
            { 
                int uu=0; qcnt++; 
                while (x!=uu) 
                    uu=stack[top--],num[qcnt]++,visit[uu]=0,belong[uu]=qcnt;  
            } 
    } 
    void reBuildGraph()
    {
        for (int i=1; i<=n; i++) 
            for (int j=head[i]; j; j=edge[j].next) 
                if (belong[i]!=belong[edge[j].to]) 
                    insertroad(belong[i],belong[edge[j].to]); 
    }
    void DP(int now)
    {
        visit[now]=1;
        for (int i=last[now]; i; i=road[i].next)
            {
                if (!visit[road[i].to]) DP(road[i].to);
                dp[now]=max(dp[now],dp[road[i].to]);
            }
        dp[now]+=num[now];
        ans=max(ans,dp[now]);
    }
    int main()
    {
        n=read(); r=read(); c=read();
        for (int i=1; i<=n; i++)
            {
                x[i]=read(),y[i]=read(),t[i]=read();
                mp[x[i]][y[i]]=i; h[x[i]].push_back(i); l[y[i]].push_back(i);
            }
        BuildGraph();
        for (int i=1; i<=n; i++) if (!dfn[i]) Tarjan(i);
        reBuildGraph();
        for (int i=1; i<=qcnt; i++) if (!visit[i]) DP(i);
        printf("%d
    ",ans); 
        return 0;
    }

    shabi题卡时卡内存是什么意思??

  • 相关阅读:
    推荐美丽的flash网页MP3音乐播放器
    android混合动画实现
    swift UI专项训练39 用Swift实现摇一摇功能
    The return type is incompatible with JspSourceDependent.getDependants():JasperException问题分析与解决方法
    【翻译自mos文章】注意: ASMB process exiting due to lack of ASM file activity
    表格对象QTableWidget相关常见方法
    python 加密解密
    python报错ordinal not in range(128)
    scp,ssh双机互信操作步骤
    PyQt多窗口调用
  • 原文地址:https://www.cnblogs.com/DaD3zZ-Beyonder/p/5557758.html
Copyright © 2011-2022 走看看