BZOJ1924 SDOI2010 所驼门王的宝藏 连通性+拓扑排序

题意:给定一个N*M的网格,有些格为特殊格:1、可以传送到同一列的某一格  2、可以传送到同一行的某一格  3、可以传送到周围八个格的某一格。可以任意选择开始的格,结束的格不限定,除了特殊格外其他格均不与其他格相连,求可以经过的最多不同格子数。

题解:每个门向其他可以到达的有门的房间连边,然后缩点,拓扑排序跑最长路(这玩意卡空间还是蛮恶心的)

#include <map>
#include <queue>
#include <stack>
#include <vector>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
using namespace std;
#define ll long long

const int MAXN=100000+2;
const int X[]={-1,-1,-1,0,1,1,1,0};
const int Y[]={-1,0,1,1,1,0,-1,-1};
struct HASH{
    int u;
    HASH *next;
    HASH(){}
    HASH(int _u,HASH *_next):u(_u),next(_next){}
}*table[MAXN],mem[80*MAXN],*node[MAXN];
int N,R,C,cnt,x[MAXN],y[MAXN],t[MAXN],c[MAXN],n[MAXN],f[MAXN],d[MAXN],ans;
int dfn[MAXN],low[MAXN],scc,depth;
bool flag[MAXN];
map<int,int> m;
stack<int> s;
queue<int> q;
vector<int> line[10*MAXN],row[10*MAXN];

void Insert1(int u,int v){ table[u]=&(mem[cnt++]=HASH(v,table[u]));}

void Insert2(int u,int v){ node[u]=&(mem[cnt++]=HASH(v,node[u])),d[v]++;}

void Tarjan(int x){
    dfn[x]=low[x]=++depth,flag[x]=1,s.push(x);
    for(HASH *p=table[x];p;p=p->next)
        if(!dfn[p->u]) Tarjan(p->u),low[x]=min(low[x],low[p->u]);
        else if(flag[p->u]) low[x]=min(low[x],dfn[p->u]);

    if(dfn[x]==low[x]){
        int t=0;scc++;
        while(t!=x){
            t=s.top(),s.pop(),flag[t]=0;
            n[scc]++,f[t]=scc;
        }
    }
}

void Topological_Sort(){
    for(int i=1;i<=scc;i++)
        if(!d[i]) q.push(i),c[i]=n[i];

    int x;
    while(!q.empty()){
        x=q.front(),q.pop();
        for(HASH *p=node[x];p;p=p->next){
            d[p->u]--;
            if(!d[p->u]) q.push(p->u);
            c[p->u]=max(c[p->u],c[x]+n[p->u]);
        }
    }
}

int main(){
    cin >> N >> R >> C;
    for(int i=1;i<=N;i++){
        cin >> x[i] >> y[i] >> t[i];
        m[(ll)(x[i]-1)*C+y[i]]=i;
        line[x[i]].push_back(i);
        row[y[i]].push_back(i);
    }

    for(int i=1;i<=N;i++){
        if(t[i]==1)
            for(int j=0;j<line[x[i]].size();j++)
                if(line[x[i]][j]!=i) Insert1(i,line[x[i]][j]);
        if(t[i]==2)
            for(int j=0;j<row[y[i]].size();j++)
                if(row[y[i]][j]!=i) Insert1(i,row[y[i]][j]);
        if(t[i]==3)
            for(int j=0;j<8;j++)
                if(m[(ll)(x[i]+X[j]-1)*C+y[i]+Y[j]]) Insert1(i,m[(x[i]+X[j]-1)*C+y[i]+Y[j]]);
    }

    for(int i=1;i<=N;i++)
        if(!dfn[i]) Tarjan(i);
    for(int i=1;i<=N;i++)
        for(HASH *p=table[i];p;p=p->next)
            if(f[i]!=f[p->u]) Insert2(f[i],f[p->u]);

    Topological_Sort();
    for(int i=1;i<=scc;i++) ans=max(ans,c[i]);
    cout << ans << endl;

    return 0;
}
View Code

 

posted @ 2017-02-28 00:24  WDZRMPCBIT  阅读(190)  评论(0编辑  收藏  举报