山东济南彤昌机械科技有限公司 山东济南江鹏工贸游有限公司

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\n",ans);
105 }

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

posted on 2016-02-27 10:54  hahalidaxin  阅读(238)  评论(0编辑  收藏  举报