1924: [Sdoi2010]所驼门王的宝藏 tarjan缩点+dp最长路

读完题感觉很是凌乱,看到数据范围又一阵冷汗,仔细看一下题,其实就是给你了点之间的关系,建边后先缩一下点,重建图后dp一下就好了。
好吧用了一下stl。。


#include<iostream>
#include<cstdio>
#include<vector>
#include<map>
#define N 1000005
using namespace std;
int n,r,c,st,cnt,cnt0,tot,scc,top,ans;
int x[N],y[N],opt[N],dfn[N],low[N],stack[N],head[N],head0[N],belong[N],num[N],deep[N];
int next[N],next0[N],list[N],list0[N];
bool inset[N],v[N];
vector <int> a[N],b[N];
map <int,int> mp[N];
int dx[8]={-1,-1,-1,0,1,1,1,0};
int dy[8]={-1,0,1,1,1,0,-1,-1};
inline int read()
{
    int a=0,f=1; char c=getchar();
    while (c<'0'||c>'9') {if (c=='-') f=-1; c=getchar();}
    while (c>='0'&&c<='9') {a=a*10+c-'0'; c=getchar();}
    return a*f;
}
inline void insert(int x,int y)
{
    next[++cnt]=head[x];
    head[x]=cnt;
    list[cnt]=y;
}
inline void insert0(int x,int y)
{
    next0[++cnt0]=head0[x];
    head0[x]=cnt0;
    list0[cnt0]=y;
}
inline void build()
{
    for (int i=1;i<=r;i++)
        for (int j=0;j<a[i].size();j++)
            if (opt[a[i][j]]==1) 
            {
                for (int k=0;k<a[i].size();k++)
                {
                    if (k==j) continue;
                    insert(a[i][j],a[i][k]);
                    if (opt[a[i][k]]==1) insert(a[i][k],a[i][j]);
                }
                break;
            }
    for (int i=1;i<=c;i++)
        for (int j=0;j<b[i].size();j++)
            if (opt[b[i][j]]==2)
            {
                for (int k=0;k<b[i].size();k++)
                {
                    if (k==j) continue;
                    insert(b[i][j],b[i][k]);
                    if (opt[b[i][k]]==2) insert(b[i][k],b[i][j]);
                }
                break;
            }
    for (int i=1;i<=n;i++)
        if (opt[i]==3)
            for (int j=0;j<8;j++)
            {
                int xx=x[i]+dx[j],yy=y[i]+dy[j];
                if (mp[xx][yy]) insert(i,mp[xx][yy]);
            }
}
void dfs(int x)
{
    dfn[x]=low[x]=++tot;
    inset[x]=1;
    stack[++top]=x;
    for (int i=head[x];i;i=next[i])
        if (!dfn[list[i]])
        {
            dfs(list[i]);
            low[x]=min(low[x],low[list[i]]);
        }
        else if (inset[list[i]]) low[x]=min(low[x],dfn[list[i]]);
    if (low[x]==dfn[x])
    {
        int i=-1; scc++;
        while (i!=x)
        {
            i=stack[top--];
            inset[i]=0;
            belong[i]=scc;
            num[scc]++;
        }
    }
}
inline void tarjan()
{
    for (int i=1;i<=n;i++) if (!dfn[i]) dfs(i);
}
inline void rebuild()
{
    for (int i=1;i<=n;i++)
        for (int j=head[i];j;j=next[j])
            if (belong[i]!=belong[list[j]])
                insert0(belong[i],belong[list[j]]);
}
void dp(int x)
{
    v[x]=1;
    for (int i=head0[x];i;i=next0[i])
    {
        if (!v[list0[i]]) dp(list0[i]);
        deep[x]=max(deep[x],deep[list0[i]]);
    }
    deep[x]+=num[x];
    ans=max(ans,deep[x]);
}
int main()
{
    n=read(); r=read(); c=read();
    for (int i=1;i<=n;i++)
    {
        x[i]=read(),y[i]=read(),opt[i]=read();
        mp[x[i]][y[i]]=i;
        a[x[i]].push_back(i);
        b[y[i]].push_back(i);
    }
    build();
    tarjan();
    rebuild();
    for (int i=1;i<=scc;i++)
        if (!v[i]) dp(i);
    cout << ans;
    return 0;
}



你可能感兴趣的:(1924: [Sdoi2010]所驼门王的宝藏 tarjan缩点+dp最长路)