• bzoj 1924 [Sdoi2010]所驼门王的宝藏(构图,SCC,DP)


    Description

    Input

    第一行给出三个正整数 N, R, C。 以下 N 行,每行给出一扇传送门的信息,包含三个正整数xi, yi, Ti,表示该传送门设在位于第 xi行第yi列的藏宝宫室,类型为 Ti。Ti是一个1~3间的整数, 1表示可以传送到第 xi行任意一列的“横天门”,2表示可以传送到任意一行第 yi列的“纵寰门”,3表示可以传送到周围 8格宫室的“ziyoumen”。 保证 1≤xi≤R,1≤yi≤C,所有的传送门位置互不相同。

    Output

    只有一个正整数,表示你确定的路线所经过不同藏宝宫室的最大数目。

    Sample Input

    10 7 7
    2 2 1
    2 4 2
    1 7 2
    2 7 3
    4 2 2
    4 4 1
    6 7 3
    7 7 1
    7 5 2
    5 2 1

    Sample Output

    9

    【思路】

           构图,SCC,DP

           因为只有宝藏室有门所以传送到空房间是没有意义的,这样可以将n个宝藏室构图。

           求出SCC,对于一个SCC内的任意节点可以互相到达而到达次数没有限制,所以缩点,将点权设为SCC的结点数,这样问题就变成了求DAG上的一条最大点权路,可以用DP求解。

           需要注意的是DAG不一定连通。

       

    【代码】

      1 #include<set>
      2 #include<stack>
      3 #include<vector>
      4 #include<cstdio>
      5 #include<cstring>
      6 #include<iostream>
      7 #include<algorithm>
      8 #define FOR(a,b,c) for(int a=(b);a<=(c);a++)
      9 using namespace std;
     10 
     11 const int N = 2*1e5+10; 
     12 struct Node{
     13     int x,y,id;
     14     bool operator < (const Node& rhs) const{
     15         return x<rhs.x || (x==rhs.x&&y<rhs.y);
     16     }
     17 };
     18 void read(int& x) {
     19     char c=getchar(); int f=1; x=0;
     20     while(!isdigit(c)) {if(c=='-')f=-1; c=getchar();}
     21     while(isdigit(c)) x=x*10+c-'0',c=getchar();
     22     x*=f;
     23 }
     24 int n,R,C,val[N],f[N],x[N],y[N],z[N],in[N];
     25 vector<int> g[N],G[N],quex[N],quey[N];
     26 int dfsc,pre[N],lowlink[N],sccno[N],scccnt;
     27 stack<int> S; set<Node> xy;
     28 
     29 void dfs(int u) {
     30     pre[u]=lowlink[u]=++dfsc;
     31     S.push(u);
     32     FOR(i,0,(int)g[u].size()-1) {
     33         int v=g[u][i];
     34         if(!pre[v]) {
     35             dfs(v);
     36             lowlink[u]=min(lowlink[u],lowlink[v]);
     37         }
     38         else if(!sccno[v]) {
     39             lowlink[u]=min(lowlink[u],pre[v]);
     40         }
     41     }
     42     if(lowlink[u]==pre[u]) {
     43         ++scccnt;
     44         for(;;) {
     45             int x=S.top(); S.pop();
     46             sccno[x]=scccnt; 
     47             if(x==u) break;
     48         }
     49     }
     50 }
     51 
     52 int dp(int u) {
     53     int& ans=f[u];
     54     if(ans) return ans;
     55     FOR(i,0,(int)G[u].size()-1)
     56         ans=max(ans,dp(G[u][i]));
     57     ans+=val[u]; 
     58     return ans;
     59 }
     60 
     61 void get_graph() {
     62     FOR(i,1,n) {
     63         read(x[i]),read(y[i]),read(z[i]);
     64         quex[x[i]].push_back(i),quey[y[i]].push_back(i);
     65         xy.insert((Node){x[i],y[i],i});
     66     }
     67     FOR(i,1,n) {
     68         if(z[i]==1) {
     69             FOR(j,0,(int)quex[x[i]].size()-1)
     70                 if(i!=quex[x[i]][j]) g[i].push_back(quex[x[i]][j]);
     71         }
     72         else if(z[i]==2) {
     73             FOR(j,0,(int)quey[y[i]].size()-1)
     74                 if(i!=quey[y[i]][j]) g[i].push_back(quey[y[i]][j]);
     75         } else {
     76             FOR(dx,-1,1) FOR(dy,-1,1) if(dx!=0||dy!=0) {
     77                 int xx=x[i]+dx,yy=y[i]+dy;
     78                 Node u=*xy.find((Node){xx,yy,0});
     79                 if(u.x==xx&&u.y==yy) g[i].push_back(u.id);
     80             }
     81         }
     82     }
     83 }
     84 
     85 int main() {
     86     //freopen("in.in","r",stdin);
     87     //freopen("out.out","w",stdout);
     88     read(n),read(R),read(C);
     89     get_graph();
     90     FOR(i,1,n) if(!pre[i]) dfs(i);
     91     FOR(u,1,n) {
     92         val[sccno[u]]++;
     93         FOR(j,0,(int)g[u].size()-1) {
     94             int v=g[u][j];
     95             if(sccno[v]!=sccno[u])  {
     96                 in[sccno[v]]++;
     97                 G[sccno[u]].push_back(sccno[v]);
     98             }
     99         }
    100     }
    101     int ans=0;
    102     FOR(i,1,scccnt)
    103         if(!in[i]) ans=max(ans,dp(i));
    104     printf("%d
    ",ans);
    105 }

     ps:万万没想到,bokeyuan竟然和谐free gate

  • 相关阅读:
    初识Activity
    贝叶斯公式由浅入深大讲解—AI基础算法入门【转】
    jz2440使用openjtag+openocd+eclipse调试【学习笔记】
    win10下搭建jz2440v3(arm s3c2440)开发及gdb调试环境【转】
    Eclipse安装zylin[转]
    Ubuntu 16.04下EasyOpenJTAG+OpenOCD的安装和使用【转】
    如何退出minicom【学习笔记】
    Python Matplotlib简易教程【转】
    anacoda的spyder在调用matplotlib的时候无法显示动画效果【学习笔记】
    Spyder如何在弹出框绘图【转】
  • 原文地址:https://www.cnblogs.com/lidaxin/p/5222477.html
Copyright © 2020-2023  润新知