BZOJ1924_所驼门王的宝藏_KEY

题目传送门

这道题苟了我好久,因为链表的内存问题,之后再细讲。

首先这是一道Tarjan+DAG上DP的题目。

有三种门,对于每种门可以和其他门相连。即连边。

使用链表快速查询连边。

建完图后可以进行Tarjan缩点。

然后做一遍DAG上DP就好了。(记搜)

然后因为建图时会有很多条边,而行列最多只有100000个,所以要分开定义。

不然会爆内存。

code:

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;

int read()
{
    char c;while(c=getchar(),c<'0'||c>'9');
    int x=c-'0';while(c=getchar(),c>='0'&&c<='9')x=x*10+c-'0';
    return x;
}

int N,R,C,x,y,fx,fy,o,a[100005][4];

struct list{
    int head[4000005],nxt[4000005],To[4000005],cnt;
    list(){memset(head,-1,sizeof head);memset(nxt,-1,sizeof nxt);}
    
    void add(int x,int y){
        To[cnt]=y;
        nxt[cnt]=head[x];
        head[x]=cnt;
        cnt++;
    }
}M,NM;

struct list2{
    int head[100005],nxt[100005],To[100005],cnt;
    list2(){memset(head,-1,sizeof head);memset(nxt,-1,sizeof nxt);}
    
    void add(int x,int y){
        To[cnt]=y;
        nxt[cnt]=head[x];
        head[x]=cnt;
        cnt++;
    }
}A,B;

int DFN[100005],LOW[100005],stack[100005],top,cnt,vis[100005],fa[100005];
int otk[100005],f[100005],sk[100005],ans;

void tarjan(int now)
{
    stack[++top]=now;
    DFN[now]=LOW[now]=++cnt;
    vis[now]=1;
        for(int i=M.head[now];i!=-1;i=M.nxt[i]){
            if(!DFN[M.To[i]])tarjan(M.To[i]),LOW[now]=min(LOW[now],LOW[M.To[i]]);
            else if(vis[M.To[i]])LOW[now]=min(LOW[now],DFN[M.To[i]]);
        }
    if(DFN[now]==LOW[now]){
        while(stack[top]!=now)
            fa[stack[top]]=now,sk[now]++,vis[stack[top]]=0,top--;
        fa[stack[top]]=now;
        sk[now]++;
        vis[stack[top--]]=0;
    }
    return ;
}

int dfs(int now)
{
    if(vis[now])return f[now];
    vis[now]=1;
        for(int i=NM.head[now];i!=-1;i=NM.nxt[i]){
            f[now]=max(f[now],dfs(NM.To[i]));
        }
    f[now]+=sk[now];
    ans=max(ans,f[now]);
    return f[now];
}

int main()
{
    N=read(),R=read(),C=read();
    register int i,j,k;
        for(i=1;i<=N;i++){
            a[i][1]=read(),a[i][2]=read(),a[i][3]=read();
            A.add(a[i][1],i);B.add(a[i][2],i);
        }
        for(i=1;i<=N;i++){
            x=a[i][1],y=a[i][2],o=a[i][3];
            if(o==1)
                for(j=A.head[x];j!=-1;j=A.nxt[j])
                    if(A.To[j]!=i)M.add(i,A.To[j]);
            if(o==2)
                for(j=B.head[y];j!=-1;j=B.nxt[j])
                    if(B.To[j]!=i)M.add(i,B.To[j]);
            if(o==3){
                for(k=-1;k<2;k++)
                for(j=A.head[x+k];j!=-1;j=A.nxt[j]){
                    fx=a[A.To[j]][1],fy=a[A.To[j]][2];
                    if(fx<=x+1&&fx>=x-1&&fy<=y+1&&fy>=y-1&&A.To[j]!=i)
                        M.add(i,A.To[j]);
                }
            }
        }
        for(i=1;i<=N;i++)if(!DFN[i])tarjan(i);
    memset(vis,0,sizeof vis);
        for(i=1;i<=N;i++){
            if(!vis[i]){vis[i]=1;
                for(j=M.head[i];j!=-1;j=M.nxt[j]){
                    if(fa[M.To[j]]!=fa[i])
                    otk[fa[M.To[j]]]++;
                }
            }
        }
        for(i=1;i<=N;i++)
            for(j=M.head[i];j!=-1;j=M.nxt[j])
                if(fa[i]!=fa[M.To[j]])NM.add(fa[i],fa[M.To[j]]);
    memset(vis,0,sizeof vis);
        for(i=1;i<=N;i++)
            if(!otk[fa[i]]&&!vis[fa[i]])
                dfs(i);
    printf("%d",ans);
    return 0;
}

Vector版传送门

原文地址:https://www.cnblogs.com/Cptraser/p/8488623.html