zoukankan      html  css  js  c++  java
  • BZOJ1924:[SDOI2010]所驼门王的宝藏(强连通分量,拓扑排序)

    Description

    Input

    第一行给出三个正整数 N, R, C。 以下 N 行,每行给出一扇传送门的信息,包含三个正整数xi, yi, Ti,表示该传送门设在位于第 xi行第yi列的藏宝宫室,类型为 Ti。Ti是一个1~3间的整数, 1表示可以传送到第 xi行任意一列的“横天门”,2表示可以传送到任意一行第 yi列的“纵寰门”,3表示可以传送到周围 8格宫室的“八方门”。 保证 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

    HINT

    N<=100000, R<=100000, C<=100000

    Solution 

    一开始的正解的想法让我以为边数太多然后叉掉了……其实是可以过的……

    很容易可以想到做法就是门和门之间连边,然后tarjan缩个点再拓扑排序跑个最长路就完事了。不过直接连边$n^2$肯定会GG。

    对于同一行的门来说,横门间显然可以相互传送,只需要选定一个横门,然后向这一行的其他横门连双向边,向这一行的其他门连单向边,这样就可以保证缩点后横门在一个强连通分量里了。列同理。

    Code

      1 #include<iostream>
      2 #include<cstring>
      3 #include<cstdio>
      4 #include<vector>
      5 #include<queue>
      6 #include<map>
      7 #define N (100009)
      8 using namespace std;
      9 
     10 struct Node{int x,y,t,id;}a[N];
     11 struct Edge{int to,next;}edge[N*10];
     12 int n,m,r,c,e1[N*3],e2[N*10],Ind[N],dp[N];
     13 int head[N],num_edge;
     14 int Dfn[N],Low[N],stack[N],ID[N],Num[N];
     15 int top,id_num,dfs_num;
     16 int dx[10]={0,0,0,1,1,1,-1,-1,-1},dy[10]={0,1,-1,0,1,-1,0,1,-1};
     17 vector<int>Line[N*10],List[N*10];
     18 map<int,int>Map[N*10];
     19 queue<int>q;
     20 bool vis[N];
     21 
     22 void add(int u,int v)
     23 {
     24     edge[++num_edge].to=v;
     25     edge[num_edge].next=head[u];
     26     head[u]=num_edge;
     27     if (!m) e1[num_edge]=u,e2[num_edge]=v;
     28 }
     29 
     30 void Tarjan(int x)
     31 {
     32     Dfn[x]=Low[x]=++dfs_num;
     33     stack[++top]=x; vis[x]=true;
     34     for (int i=head[x]; i; i=edge[i].next)
     35         if (!Dfn[edge[i].to])
     36             Tarjan(edge[i].to),Low[x]=min(Low[x],Low[edge[i].to]); 
     37         else if (vis[edge[i].to])
     38             Low[x]=min(Low[x],Dfn[edge[i].to]);
     39     if (Low[x]==Dfn[x])
     40     {
     41         vis[x]=false; ID[x]=++id_num; Num[id_num]++;
     42         while (stack[top]!=x)
     43         {
     44             vis[stack[top]]=false;
     45             Num[id_num]++;
     46             ID[stack[top--]]=id_num;
     47         }
     48         top--;
     49     }
     50 }
     51 
     52 void Add()
     53 {
     54     for (int i=1; i<=r; ++i)
     55     {
     56         int x=0,sz=Line[i].size();
     57         for (int j=0; j<sz; ++j)
     58             if (a[Line[i][j]].t==1){x=Line[i][j]; break;}
     59         if (!x) continue;
     60         for (int j=0; j<sz; ++j)
     61             if (Line[i][j]!=x)
     62             {
     63                 add(x,Line[i][j]);
     64                 if (a[Line[i][j]].t==1) add(Line[i][j],x);
     65             }
     66     }
     67     for (int i=1; i<=c; ++i)
     68     {
     69         int x=0,sz=List[i].size();
     70         for (int j=0; j<sz; ++j)
     71             if (a[List[i][j]].t==2){x=List[i][j]; break;}
     72         if (!x) continue;
     73         for (int j=0; j<sz; ++j)
     74             if (List[i][j]!=x)
     75             {
     76                 add(x,List[i][j]);
     77                 if (a[List[i][j]].t==2) add(List[i][j],x);
     78             }
     79     }
     80     for (int i=1; i<=n; ++i)
     81         if (a[i].t==3)
     82         {
     83             int x=a[i].x,y=a[i].y;
     84             for (int j=1; j<=8; ++j)
     85             {
     86                 int t=Map[x+dx[j]][y+dy[j]];
     87                 if (t) add(i,t);
     88             }
     89         }
     90 }
     91 
     92 void Toposort()
     93 {
     94     int ans=0;
     95     for (int i=1; i<=id_num; ++i) ans=max(ans,Num[i]);
     96     for (int i=1; i<=id_num; ++i) if (!Ind[i]) q.push(i),dp[i]=Num[i];
     97     while (!q.empty())
     98     {
     99         int x=q.front(); q.pop();
    100         for (int i=head[x]; i; i=edge[i].next)
    101         {
    102             int y=edge[i].to; Ind[y]--;
    103             if(!Ind[y]) q.push(y);
    104             dp[y]=max(dp[y],dp[x]+Num[y]);
    105             ans=max(ans,dp[y]);
    106         }
    107     }
    108     printf("%d
    ",ans);
    109 }
    110 
    111 int main()
    112 {
    113     scanf("%d%d%d",&n,&r,&c);
    114     for (int i=1; i<=n; ++i)
    115     {
    116         scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].t);
    117         Line[a[i].x].push_back(i);
    118         List[a[i].y].push_back(i);
    119         Map[a[i].x][a[i].y]=i;
    120     }
    121     Add();
    122     for (int i=1; i<=n; ++i)
    123         if (!Dfn[i]) Tarjan(i);
    124     
    125     memset(head,0,sizeof(head));
    126     m=num_edge; num_edge=0;
    127     for (int i=1; i<=m; ++i)
    128         if (ID[e1[i]]!=ID[e2[i]])
    129             add(ID[e1[i]],ID[e2[i]]),Ind[ID[e2[i]]]++;
    130     Toposort();
    131 }
  • 相关阅读:
    数据库的查询笔记
    数据库设计第3级的阶梯:构建表
    数据库使用学习笔记
    index()
    面向对象写法的拖拽
    js面向对象
    laytpl.js 模板使用记录
    面试总结
    JS的基础类型与引用类型
    jQuery两种扩展插件的方式
  • 原文地址:https://www.cnblogs.com/refun/p/9614719.html
Copyright © 2011-2022 走看看