BZOJ 1924 && Luogu P2403 [SDOI2010]所驼门王的宝藏 恶心建图+缩点DP

记住:map一定要这么用:

if(mp[x[i]+dx[j]].find(y[i]+dy[j])!=mp[x[i]+dx[j]].end()) add(i,mp[x[i]+dx[j]][y[i]+dy[j]]);

  而不是

R tmp=mp[x[i]+dx[j]][y[i]+dy[j]];
if(tmp) add(i,tmp);

别问我为什么QAQ

建图:选定一个横天门,向在这一行上的横天门连无向边,剩下的门连有向边;纵寰门一样的方法

用map判 自由_门 旁边八个点是否存在,存在就连边;

最后tarjan缩点,用dp求最长路

#include<cstdio>
#include<iostream>
#include<cstring>
#include<vector>
#include<map>
#define R register int
const int dx[]={0,1,1,1,0,-1,-1,-1},dy[]={1,1,0,-1,-1,-1,0,1};
using namespace std;
inline int g() {
    R ret=0; register char ch; while(!isdigit(ch=getchar())) ;
    do ret=ret*10+(ch^48); while(isdigit(ch=getchar())); return ret;
}
#define pb(x) push_back(x) 
int k,n,m,cnt=1,ind,cc,top,ans,num;
int lst[100010],lst2[100010],x[100010],y[100010],op[100010],d[100010];
int vr[1000010],nxt[1000010],fir[1000010],dfn[100010],scc[100010],stk[100010],low[100010],c[100010];
vector<int>a[1000010],b[1000010];
map<int,int> mp[1000010];
bool vis[100010];
inline void add(int u,int v) {if(u==v) return ;vr[++cnt]=v,nxt[cnt]=fir[u],fir[u]=cnt;}
inline void init() {
    for(R i=1;i<=n;++i) {
        R x=0,sz=a[i].size();
        for(R j=0;j<sz;++j) if(op[a[i][j]]==1) {x=a[i][j]; break;}
        for(R j=0;j<sz;++j) {add(x,a[i][j]); if(op[a[i][j]]==1) add(a[i][j],x);}
    }
    for(R i=1;i<=m;++i) {
        R x=0,sz=b[i].size();
        for(R j=0;j<sz;++j) if(op[b[i][j]]==2) {x=b[i][j]; break;}
        for(R j=0;j<sz;++j) {add(x,b[i][j]); if(op[b[i][j]]==2) add(b[i][j],x);}
    }
    for(R i=1;i<=k;++i) if(op[i]==3) for(R j=0;j<8;++j) 
        if(mp[x[i]+dx[j]].find(y[i]+dy[j])!=mp[x[i]+dx[j]].end()) add(i,mp[x[i]+dx[j]][y[i]+dy[j]]);void tarjan(int u) { low[u]=dfn[u]=++num; stk[++top]=u,vis[u]=true;
    for(R i=fir[u];i;i=nxt[i]) { R v=vr[i];
        if(!dfn[v]) {
            tarjan(v);
            low[u]=min(low[u],low[v]);
        } else if(vis[v]) low[u]=min(low[u],dfn[v]);
    } if(low[u]==dfn[u]) {
        R tmp; ++cc;
        do tmp=stk[top],--top,vis[tmp]=false,c[tmp]=cc,++scc[cc]; while(tmp!=u);
    }
}
int vv[1000010],nn[1000010],ff[1000010];
inline void addc(int u,int v) {vv[++cnt]=v,nn[cnt]=ff[u],ff[u]=cnt;}
inline void solve() {
    cnt=1; for(R u=1;u<=k;++u) for(R i=fir[u];i;i=nxt[i]) 
        if(c[u]!=c[vr[i]]) addc(c[u],c[vr[i]]);
}
inline void dp(int u) { vis[u]=true;
    for(R i=ff[u];i;i=nn[i]) { R v=vv[i];
        if(!vis[v]) dp(v);
        d[u]=max(d[v],d[u]);
    } d[u]+=scc[u]; ans=max(d[u],ans);
}
signed main() {
    k=g(),n=g(),m=g();
    for(R i=1;i<=k;++i) {
        x[i]=g(),y[i]=g(),op[i]=g();
        mp[x[i]][y[i]]=i;
        a[x[i]].pb(i),b[y[i]].pb(i);
    } init(); for(R i=1;i<=k;++i) if(!dfn[i]) tarjan(i);
    solve(); memset(vis,false,sizeof(vis));
    for(R i=1;i<=cc;++i) if(!vis[i]) dp(i);
    printf("%d\n",ans); return 0;
}

2019.04.21

upd:5秒后 (发布时显示:博文中含有违规内容: 自_由_门! (并没有下划线)    ????不知所言)

posted @ 2019-04-21 19:42  LuitaryiJack  阅读(200)  评论(0编辑  收藏  举报