【题解】SDOI2010所驼门王的宝藏(强连通分量+优化建图)

【题解】SDOI2010所驼门王的宝藏(强连通分量+优化建图)

最开始我想写线段树优化建图的说,数据结构学傻了233

虽然矩阵很大,但是没什么用,真正有用的是那些关键点

考虑关键点的类型:

  • 横走型
  • 竖走型
  • 八连通型

本质上只有两种类型(走一大串/走八连通),我们考虑这样一种建图方法:

  • 对于每一行每一列建立一个点(点权为\(0\))
  • 对于关键点建立一个点(点权为\(1\))

然后考虑这样一种建图方式,得到一个有点权无边权图

  • 关键点所在的行与列无偿地向这个关键点连边
  • 横走型的关键点向行连一条边,竖走型同理
  • 八连通型直接向周围的关键点连边

题目要求走到的点最多,也就是求一条最长路径,但是显然这个图上可能有正环,但是点权贡献只能算一次,自然想到直接缩点。缩完点后得到一个\(DAG\),直接在这个\(DAG\)上\(dp\)

\(dp_i\)表示从这个节点出发最长的路径,直接转移。

分析点数,显然是\(O(3n)\),分析边数,一个点最多连接十条边,\(tarjin\)是\(O(n)\)的,但是我们用了\(map\)所以复杂度\(O(n\log n)\),实际上,直接用unordered_map就是\(O(n)\)了,就帅一点...

至于实现,直接用\(map\)存std::pair < int ,int >就好了

//@winlere
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<map>

using namespace std;  typedef long long ll;
inline int qr(){
      register int ret=0,f=0;
      register char c=getchar();
      while(c<48||c>57)f|=c==45,c=getchar();
      while(c>=48&&c<=57) ret=ret*10+c-48,c=getchar();
      return f?-ret:ret;
}

const int maxn=1e5+5;
struct E{
      int to,nx;
      E(){to=nx=0;}
      E(const int&a,const int&b){to=a;nx=b;}
};
vector < E > e,e2;

pair < int ,int > node[maxn];
int head[maxn*3];
int head2[maxn*3];
int TT[maxn];
int dp[maxn*3];
int n,m,k;

void add2(const int&fr,const int&to){
      e2.push_back(E(to,head2[fr]));
      head2[fr]=e2.size()-1;
}
void add(const int&fr,const int&to){
      e.push_back(E(to,head[fr]));
      head[fr]=e.size()-1;
}

int idx[maxn],idy[maxn];
int w[maxn*3];
int stk[maxn*3];
int qaq,top;
int be[maxn*3];
int siz[maxn*3];
int dfn[maxn*3],low[maxn*3],in[maxn*3];
int tim,ans;
int qaqcnt;

int dfs2(const int&now){
      if(dp[now]) return dp[now];
      register int ret=0;
      for(register int t=head2[now];t;t=e2[t].nx)
        ret=max(ret,dfs2(e2[t].to));
      return dp[now]=ret+siz[now];
}

void dfs(const int&now){
      dfn[now]=low[now]=++tim;in[now]=1;stk[++top]=now;
      for(register int t=head[now];t;t=e[t].nx){
        if(!dfn[e[t].to])
          dfs(e[t].to),low[now]=min(low[now],low[e[t].to]);
        if(dfn[e[t].to]&&in[e[t].to])
          low[now]=min(low[now],dfn[e[t].to]);
      }
      if(dfn[now]==low[now]){
        register int temp=0;
        ++qaq;
        do{
          temp=stk[top--];
          in[temp]=0;siz[qaq]+=w[temp];
          be[temp]=qaq;
        }while(temp!=now);
      }
}

map < pair < int ,int > , int > s;
inline int init(const int&a,const int&b,const int&c){
      e.push_back(E());  e.push_back(E());
      e2.push_back(E()); e2.push_back(E());
      qaqcnt=k=a;n=b;m=c;
      for(register int t=1;t<=k;++t){
        register int t1=qr(),t2=qr(),t3=qr();
        node[t].first=t1;
        node[t].second=t2;
        TT[t]=t3; w[t]=1;
        s[make_pair(t1,t2)]=t;
        if(!idx[t1]) idx[t1]=++qaqcnt;
        if(!idy[t2]) idy[t2]=++qaqcnt;
        add(idx[t1],t);
        add(idy[t2],t);
      }

      for(register int t=1;t<=k;++t){
        if(TT[t]==1) add(t,idx[node[t].first]);
        if(TT[t]==2) add(t,idy[node[t].second]);
        if(TT[t]==3)
          for(register int dx=-1;dx<=1;++dx)
            for(register int dy=-1;dy<=1;++dy)
                  if(dx||dy){
                    auto f=s.find(make_pair(node[t].first+dx,node[t].second+dy));
                    if(f!=s.end()) add(t,f->second);
                  }
      }

      for(register int t=1;t<=qaqcnt;++t)
        if(!dfn[t]) dfs(t);
      for(register int t=1;t<=qaqcnt;++t)
        for(register int i=head[t];i;i=e[i].nx)
          if(be[e[i].to]!=be[t])
            add2(be[t],be[e[i].to]);
      for(register int t=1;t<=qaq;++t)
        ans=max(ans,dfs2(t));
      printf("%d\n",ans);
      return 0;
}

int main(){
      int a=qr(),b=qr(),c=qr();
      return init(a,b,c);
}

原文地址:https://www.cnblogs.com/winlere/p/11329768.html

时间: 2024-10-08 15:18:04

【题解】SDOI2010所驼门王的宝藏(强连通分量+优化建图)的相关文章

题解 P2403 【[SDOI2010]所驼门王的宝藏】

题目链接 Solution [SDOI2010]所驼门王的宝藏 题目大意:给定一个\(R\)行\(C\)列的矩阵,有些方格有宝藏和传送门.你可以从任意方格进入,到达有宝藏的宫室时可以横行任意传送.纵行任意传送.八连块任意传送(视传送门类型而定),问最多可以获得多少宝藏 分析:看到什么"传送"这类字眼我们多半就会想到图论.于是乎我们\(1min\)就可以想出一个暴力算法: 每个有宝藏的点向它可以到达的所有有宝藏的点连边,\(Tarjan\)缩点后求\(DAG\)最长路 大概有\(40\)

[SDOI2010]所驼门王的宝藏 --tarjan缩点+最长路

[SDOI2010]所驼门王的宝藏 题目描述 在宽广的非洲荒漠中,生活着一群勤劳勇敢的羊驼家族.被族人恭称为“先知”的Alpaca L. Sotomon是这个家族的领袖,外人也称其为“所驼门王”.所驼门王毕生致力于维护家族的安定与和谐,他曾亲自率军粉碎河蟹帝国主义的野蛮侵略,为族人立下赫赫战功.所驼门王一生财宝无数,但因其生性节俭低调,他将财宝埋藏在自己设计的地下宫殿里,这也是今天Henry Curtis故事的起点.Henry是一个爱财如命的贪婪家伙,而又非常聪明,他费尽心机谋划了这次盗窃行动,

洛谷2403 [SDOI2010]所驼门王的宝藏

题目描述 在宽广的非洲荒漠中,生活着一群勤劳勇敢的羊驼家族.被族人恭称为“先知”的Alpaca L. Sotomon是这个家族的领袖,外人也称其为“所驼门王”.所驼门王毕生致力于维护家族的安定与和谐,他曾亲自率军粉碎河蟹帝国主义的野蛮侵略,为族人立下赫赫战功.所驼门王一生财宝无数,但因其生性节俭低调,他将财宝埋藏在自己设计的地下宫殿里,这也是今天Henry Curtis故事的起点.Henry是一个爱财如命的贪婪家伙,而又非常聪明,他费尽心机谋划了这次盗窃行动,破解重重机关后来到这座地下宫殿前.

[SDOI2010]所驼门王的宝藏

题目描述 在宽广的非洲荒漠中,生活着一群勤劳勇敢的羊驼家族.被族人恭称为"先知"的Alpaca L. Sotomon是这个家族的领袖,外人也称其为"所驼门王".所驼门王毕生致力于维护家族的安定与和谐,他曾亲自率军粉碎河蟹帝国主义的野蛮侵略,为族人 立下赫赫战功.所驼门王一生财宝无数,但因其生性节俭低调,他将财宝埋藏在自己设计的地下宫殿里,这也是今天Henry Curtis故事的起点.Henry是一个爱财如命的贪婪家伙,而又非常聪明,他费尽心机谋划了这次盗窃行动,破解

BZOJ 1924: [Sdoi2010]所驼门王的宝藏 【tarjan】

Description 在宽广的非洲荒漠中,生活着一群勤劳勇敢的羊驼家族.被族人恭称为“先 知”的Alpaca L. Sotomon 是这个家族的领袖,外人也称其为“所驼门王”.所 驼门王毕生致力于维护家族的安定与和谐,他曾亲自率军粉碎河蟹帝国主义的野 蛮侵略,为族人立下赫赫战功.所驼门王一生财宝无数,但因其生性节俭低调, 他将财宝埋藏在自己设计的地下宫殿里,这也是今天Henry Curtis 故事的起点. Henry 是一个爱财如命的贪婪家伙,而又非常聪明,他费尽心机谋划了这次盗窃 行动,破解

P2403 [SDOI2010]所驼门王的宝藏

https://www.luogu.org/problemnew/show/P2403 题目描述 在宽广的非洲荒漠中,生活着一群勤劳勇敢的羊驼家族.被族人恭称为“先知”的Alpaca L. Sotomon是这个家族的领袖,外人也称其为“所驼门王”.所驼门王毕生致力于维护家族的安定与和谐,他曾亲自率军粉碎河蟹帝国主义的野蛮侵略,为族人立下赫赫战功.所驼门王一生财宝无数,但因其生性节俭低调,他将财宝埋藏在自己设计的地下宫殿里,这也是今天Henry Curtis故事的起点.Henry是一个爱财如命的贪

[SDOI2010] 所驼门王的宝藏 [建图+tarjan缩点+DAG dp]

题面传送门: 传送门 思路: 看完题建模,容易得出是求单向图最长路径的问题 那么把这张图缩强联通分量,再在DAG上面DP即可 然而 这道题的建图实际上才是真正的考点 如果对于每一个点都直接连边到它所有的后继节点,那么可以被卡掉(1e5个点在同一行上) 考虑改变思路,运用网络流建图中的一个常用技巧:把横边和竖边映射成点,再从每个点向所在横坐标.纵坐标代表的点连边即可 这样会有2e6+1e5个点,但是tarjan算法效率O(n),完全无压力 自由(和谐)门的话,目前还没有比较好的方法解决 上网看了一

bzoj 1924: [Sdoi2010]所驼门王的宝藏

23333这个垃圾题之前扒过题解了2333 然而这一次做又错了... 直接暴力连边,然后缩一下点,重构变成DAG,然后DP.. (然而在打tarjan的时候忘掉了inq[now]=0....而且把DP搞成了搜索2333) (附:此题内存玄学) 1 #include<cstdio> 2 #include<iostream> 3 #include<algorithm> 4 #include<map> 5 #define N 1000005 6 #define L

【BZOJ-1924】所驼门王的宝藏 Tarjan缩点(+拓扑排序) + 拓扑图DP

1924: [Sdoi2010]所驼门王的宝藏 Time Limit: 5 Sec  Memory Limit: 128 MBSubmit: 787  Solved: 318[Submit][Status][Discuss] Description Input 第一行给出三个正整数 N, R, C. 以下 N 行,每行给出一扇传送门的信息,包含三个正整数xi, yi, Ti,表示该传送门设在位于第 xi行第yi列的藏宝宫室,类型为 Ti.Ti是一个1~3间的整数, 1表示可以传送到第 xi行任意