[无聊测试赛] T10 所驼门王的宝藏

码农题.思维难度中等,难在调试

建边方法:分别将x和y排序,对每个点,对它旁边所有的x/y连边(如果他需要). 开map记录点的位置,对于每个点,如果他的九宫格之内有其他点,就对他连边

注意排序会使点的顺序混乱,故需要在状态里将点的id保存

连完边跑tarjan缩点.易证如果你能到一个环内的某个点,你就可以到达这个环内的每个点.每个环的权值为他里面的点数量.将各个环转化为一个新图

可以发现新图已经转化为一个DAG.可以选择用dfs/topo来记录答案.这里我选择用dfs.

dfs每个未经过的点并统计经过这个点能得到的宝藏数量,取最大值

#include <iostream>
#include <algorithm>
#include <queue>
#include <vector>
#include <unordered_map>
#include <cstring>
#include <stack>
using namespace std;
const int MAXN = 1e5+5;
int n,r,c,dp[MAXN],curr,ans;

int pre,dfn[MAXN],low[MAXN],head[MAXN],num[MAXN],in[MAXN];
unordered_map<int, unordered_map<int,int> > mp, inq;
vector<int> adj[MAXN],adj2[MAXN],tmp[MAXN];
stack<int> st;
int x_[8] = {1,0,-1,0,1,1,-1,-1};
int y_[8] = {0,1,0,-1,1,-1,1,-1};//九宫格
bool vis[MAXN];
struct Edge{
  int x,y,type,id;
}edge[MAXN],edge2[MAXN];
inline bool sorted1(Edge a, Edge b){
  return a.x<b.x || (a.x==b.x && a.type==1);
}//x排序
inline bool sorted2(Edge a, Edge b){
  return a.y<b.y || (a.y==b.y && a.type==2);
}//y排序
inline void add_x(){
  sort(edge+1,edge+n+1,sorted1);
  int prev = 0;
  for (int i=1;i<=n;i++){
    if (edge[i].type!=1) continue;//如果他自己不能连
    int f = edge[i].id;
    int nxt = i-1;
    while(nxt>0){
      if (edge[nxt].x!=edge[i].x) break;
      int t = edge[nxt].id;
      adj[f].push_back(t);
      nxt--;
    }//往左连
    nxt = i+1;
    while(nxt<=n){
      int t = edge[nxt].id;
      if (edge[nxt].x!=edge[i].x) break;
      adj[f].push_back(t);
      nxt++;
    }//往右连
  }
}
inline void add_y(){
  sort(edge+1,edge+n+1,sorted2);
  int prev = 0;
  for (int i=1;i<=n;i++){
    if (edge[i].type!=2) continue;
    int f = edge[i].id;
    int nxt = i-1;
    while(nxt>0){//往左
      int t = edge[nxt].id;
      if (edge[nxt].y!=edge[i].y) break;
      adj[f].push_back(t);
      nxt--;
    }
    nxt = i+1;
    while(nxt<=n){//往右
      int t = edge[nxt].id;
      if (edge[nxt].y!=edge[i].y) break;
      adj[f].push_back(t);
      nxt++;
    }
  }
}
inline void add_xy(){//九宫格连
  for (int i=1;i<=n;i++){
    if (edge[i].type!=3) continue;
    int f = edge[i].id;
    for (int j=0;j<8;j++){
      int to_x = edge[i].x+x_[j], to_y = edge[i].y+y_[j];
      if (mp[to_x][to_y] ){
        int t = mp[to_x][to_y];
        if (!inq[f][t]){inq[f][t] = true;adj[f].push_back(t);}
      }
    }
  }
}
void tarjan(int pos){//裸的tarjan
  st.push(pos);
  vis[pos] = true;
  dfn[pos] = low[pos] = ++pre;
  for (int v : adj[pos]){
    if (!dfn[v]){
      tarjan(v);
      low[pos] = min(low[pos],low[v]);
    }else if (vis[v]) low[pos] = min(low[pos],dfn[v]);
  }
  if (dfn[pos]==low[pos]) {
    curr++;
    while(st.size()){
      int stt = st.top();
      head[stt] = curr;
      tmp[curr].push_back(stt);
      num[curr]++;
      st.pop();
      vis[stt] = false;
      if (stt==pos) break;
    }
  }
}
void dfs(int pos){//dfs找子叶权值
  dp[pos] = num[pos];
  int addi = 0;
  for (int v : adj2[pos]){
    if (!dp[v]) dfs(v);
    addi = max(addi,dp[v]);
  }
  dp[pos]+=addi;
}
int main(){
  cin >> n >> r >> c;
  for (int i=1;i<=n;i++) {
    cin >> edge[i].x  >> edge[i].y >> edge[i].type;edge[i].id = i;
    edge2[i] = edge[i];
    mp[edge[i].x][edge[i].y] = i;
  }
  add_x();
  add_y();
  add_xy();
  for (int i=1;i<=n;i++) if (!dfn[i]) tarjan(i);

  for (int i=1;i<=curr;i++){//建新图
    memset(vis,0,sizeof(vis));
    vis[i] = true;
    for (int u : tmp[i]){
      for (int v : adj[u]){
        if (!vis[head[v]]){
          vis[head[v]] = true;
          adj2[i].push_back(head[v]);
        }
      }
    }
  }
  memset(vis,0,sizeof(vis));
  for (int i=1;i<=curr;i++){//找答案
    if (!vis[i]){
      dfs(i);
      ans = max(ans,dp[i]);
    }
  }
  cout << ans;
}

原文地址:https://www.cnblogs.com/DannyXu/p/12536357.html

时间: 2024-10-08 15:17:55

[无聊测试赛] T10 所驼门王的宝藏的相关文章

【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行任意

BZOJ 1924 所驼门王的宝藏(强连通分量+树形DP)

题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=1924 题意: 思路:首先建立所有可达点之间的有向图.之后求强连通分量SCC,缩点重新构图.然后就是一个树,树形DP一下即可. int n,r,c; map<i64,int> mp; map<int,int> mp1,mp2; struct node { int x,y,op; }; node a[N]; int visit[N]; vector<int> V1

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

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

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

[题解]SDOI2010所驼门王的宝藏(强连通分量+优化建图) 最开始我想写线段树优化建图的说,数据结构学傻了233 虽然矩阵很大,但是没什么用,真正有用的是那些关键点 考虑关键点的类型: 横走型 竖走型 八连通型 本质上只有两种类型(走一大串/走八连通),我们考虑这样一种建图方法: 对于每一行每一列建立一个点(点权为\(0\)) 对于关键点建立一个点(点权为\(1\)) 然后考虑这样一种建图方式,得到一个有点权无边权图 关键点所在的行与列无偿地向这个关键点连边 横走型的关键点向行连一条边,竖走

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

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

洛谷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是一个爱财如命的贪