BZOJ 1924 Sdoi2010 所驼门王的宝藏

题目

题解:
对于同方向(横竖的),同行最近相邻的两个连边。每个关键点被左右最近横向点连边,被上下最近纵向点连边,自由门按题意连,没有宝藏的点不连边,求强连通分量缩点后跑拓扑排序即可。
我打的好长啊。

AC Code:

#pragma GCC optimize(2)
#include<bits/stdc++.h>
#define maxn 1000006
#define maxm 100005
#define pb push_back
#define pii pair<int,int>
#define mp make_pair
#define F first
#define S second
using namespace std;
 
int n,r,c,cnt,in[maxm];
vector<int>h[maxn],z[maxn];
vector<pii>zy;
 
map<pii,int>st;
vector<int>G[maxm],V[maxm];
 
int sta[maxm],dfn[maxm],low[maxm],bl[maxm],siz[maxm],dis[maxm],scc,tim;
void dfs(int u){
    dfn[u] = low[u] = ++tim;
    sta[++sta[0]] = u;
    for(int i=0,v;i<G[u].size();i++)
        if(!dfn[v=G[u][i]]){
            dfs(v);
            low[u] = min(low[u] , low[v]);
        }
        else if(!bl[v]){
            low[u] = min(low[u] , dfn[v]);
        }
    if(low[u] == dfn[u]){
        scc++;
        for(int t=-1;t!=u;){
            bl[t = sta[sta[0]--]] = scc;
            siz[scc]++;
        }
    }
}
 
int main(){
    scanf("%d%d%d",&n,&r,&c);   
    for(int i=1;i<=n;i++){
        int x,y,t;
        scanf("%d%d%d",&x,&y,&t);
        if(t == 1) h[x].pb(y);
        if(t == 2) z[y].pb(x);
        if(t == 3) zy.pb(mp(x,y));
        st[mp(x,y)] = ++cnt;
    }
    for(int i=1;i<=r;i++)
        if(!h[i].empty()){
            sort(h[i].begin(),h[i].end());
            for(int j=0,pr=0;j<h[i].size();j++){
                int p = h[i][j];
                if(j){
                    int npr = st[mp(i,p)];
                    G[npr].pb(pr),G[pr].pb(npr);
                    pr = npr;
                }
                else pr = st[mp(i,p)];
            }
        }
    for(int i=1;i<=c;i++)
        if(!z[i].empty()){
            sort(z[i].begin(),z[i].end());
            for(int j=0,pr=0;j<z[i].size();j++){
                int p = z[i][j];
                if(j){
                    int npr = st[mp(p,i)];
                    G[npr].pb(pr) , G[pr].pb(npr);
                    pr = npr; 
                }
                else pr = st[mp(p,i)];
            }
        }
    for(int i=0;i<zy.size();i++){
        int p = st[zy[i]];
        vector<int>::iterator t = lower_bound(h[zy[i].F].begin(),h[zy[i].F].end(),zy[i].S);
        if(t != h[zy[i].F].end())
            G[st[mp(zy[i].F,*t)]].pb(p);
        if(t != h[zy[i].F].begin()){
            t--;
            G[st[mp(zy[i].F,*t)]].pb(p);
        }
         
        t = lower_bound(z[zy[i].S].begin(),z[zy[i].S].end(),zy[i].F);
        if(t != z[zy[i].S].end())
            G[st[mp(*t,zy[i].S)]].pb(p);
        if(t != z[zy[i].S].begin()){
            t--;
            G[st[mp(*t,zy[i].S)]].pb(p);
        }
         
         
        for(int j=max(-1,1-zy[i].F);j<=min(1,r-zy[i].F);j++)
            for(int k=max(-1,1-zy[i].S);k<=min(1,c-zy[i].S);k++)
                if(j || k){
                    int u = zy[i].F + j , v = zy[i].S + k;
                    if(!st.count(mp(u,v))) continue;
                    G[p].pb(st[mp(u,v)]);
                }
    }
     
    for(int i=1;i<=r;i++)
        if(!h[i].empty()){
            for(int j=0;j<h[i].size();j++){
                int pp = h[i][j] , p = st[mp(i,pp)];
                vector<int>::iterator t = lower_bound(z[pp].begin(),z[pp].end(),i);
                if(t != z[pp].end())
                    G[st[mp(*t,pp)]].pb(p);
                if(t != z[pp].begin())      
                    t--,
                    G[st[mp(*t,pp)]].pb(p);
            }
        }
         
    for(int i=1;i<=c;i++)
        if(!z[i].empty()){
            for(int j=0;j<z[i].size();j++){
                int pp = z[i][j] , p = st[mp(pp,i)];
                vector<int>::iterator t = lower_bound(h[pp].begin(),h[pp].end(),i);
                if(t != h[pp].end())
                    G[st[mp(pp,*t)]].pb(p);
                if(t != h[pp].begin())
                    t--,
                    G[st[mp(pp,*t)]].pb(p);
            }
        }
     
    for(int i=1;i<=cnt;i++)
        if(!dfn[i])
            dfs(i);
             
    for(int i=1;i<=cnt;i++)
        for(int j=0,v;j<G[i].size();j++)
            if(bl[i] != bl[v=G[i][j]])
                V[bl[i]].pb(bl[v]) , in[bl[v]] ++;
     
    queue<int>q;
    for(int i=1;i<=scc;i++)
        if(!in[i])  
            q.push(i) , dis[i] = siz[i];
    int ans = 0;
    for(int u;!q.empty();){
        u = q.front() , q.pop();
        ans = max(ans , dis[u]);
        for(int j=0,v;j<V[u].size();j++){
            in[v=V[u][j]] --;
            dis[v] = max(dis[v] , dis[u] + siz[v]);
            if(!in[v]) q.push(v);
        }
    }
     
    printf("%d\n",ans);
}

一个月后原题重错,好像短了一点。

#include<bits/stdc++.h>
#define maxn 100005
#define maxm 800005
#define pii pair<int,int>
#define mp make_pair
#define pb push_back
using namespace std;

int n,C,dp[maxn],siz[maxn],in[maxn];
int x[maxn],y[maxn],t[maxn],px[maxn],py[maxn];
int info[maxn],Prev[maxm],to[maxm],cnt_e;
void Node(int u,int v){ Prev[++cnt_e]=info[u],info[u]=cnt_e,to[cnt_e]=v; }
map<pii,int>st;
vector<int>G[maxn];
int dfn[maxn],low[maxn],c[maxn],q[maxn],L,R,scc,tot;
void dfs(int u){
	dfn[u] = low[u] = ++tot , q[R++] = u;
	for(int i=info[u],v;i;i=Prev[i])
		if(!dfn[v=to[i]]) dfs(v),low[u]=min(low[u],low[v]);
		else if(!c[v]) low[u]=min(low[u],dfn[v]);
	if(low[u] == dfn[u]){
		scc++;
		for(int t=-1;t!=u;)
			c[t=q[--R]]=scc,
			siz[scc]++;
	}
}

int main(){
	scanf("%d%d%d",&n,&R,&C);
	R=0;
	for(int i=1;i<=n;i++){
		scanf("%d%d%d",&x[i],&y[i],&t[i]);
		if(t[i] == 1){
			if(!px[x[i]]) px[x[i]] = i;
			else Node(i,px[x[i]]);
		}
		else if(t[i] == 2){
			if(!py[y[i]]) py[y[i]] = i;
			else Node(i,py[y[i]]);
		}
		st[mp(x[i],y[i])] = i;
	}
	for(int i=1;i<=n;i++){
		if(py[y[i]]) Node(py[y[i]],i);
		if(px[x[i]]) Node(px[x[i]],i);
		if(t[i] == 3){
			for(int j=x[i]-1;j<=x[i]+1;j++)
				for(int k=y[i]-1;k<=y[i]+1;k++)
					if((j!=x[i] || k!=y[i]) && st.count(mp(j,k)))
						Node(i,st[mp(j,k)]);
		}
	}
	for(int i=1;i<=n;i++)
		if(!dfn[i])
			dfs(i);
	for(int i=1;i<=n;i++)
		for(int j=info[i],v;j;j=Prev[j])
			if(c[i] != c[v=to[j]])
				G[c[i]].pb(c[v]),in[c[v]]++;
	for(int i=1;i<=scc;i++) if(!in[i]) q[R++] = i,dp[i]=siz[i];
	int ans = 0;
	for(int u;L<R;){
		ans = max(ans , dp[u=q[L++]]);
		for(int v:G[u]){
			dp[v] = max(dp[v] , dp[u] + siz[v]);
			if(!--in[v]) q[R++] = v;
		}
	}
	printf("%d\n",ans);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值