P2403 [SDOI2010] The king treasure gates camel

As a good (e), (xin) of small purple question, it is worth doing (though subject nonsense, and practice nausea)

Title Description

In broad African desert, living with a group of industrious and brave alpaca family. Christine tribe is known as the "prophet" of Alpaca L. Sotomon is the leader of the family, outsiders also referred to as "the camel door king." The camel door King devoted his life to maintain stability and harmony of the family, he had personally led his army crushed crab brutal aggression of imperialism, for the tribe set hehe exploits. The camel door Wang Yisheng countless treasures, but because of its low-key frugal nature, he will treasure buried in the underground palace's own design, which is the starting point for today Henry Curtis story. Henry is a money-grubber greedy guy, and very smart, he took great pains to plan the theft of this action to crack heavy organs came to the front of this underground palace.

Whole palace in a matrix form, between the R × C rectangular palace, where there are N buried hidden treasures between palace, palace called treasure. Palace, the inter-entity palace by rigid walls adjacent to the barrier by a palace to the other only through the inter-gate king original camel moves - Portal. The camel is the king of the N door between each room a treasure palace erected a portal, is not no treasure palace portal, all portals of the palace is divided into three:

  1. "Days horizontal door": the gate of a palace may be transmitted to any counterparts;

  2. "Atlas vertical door": the door can be transmitted to any of the palace a same column;

  3. "Any door": a door may be transmitted to the gate located in the center of a house for around 8 grid of any one palace (palace target if present).

Henry, of course thoughtful in advance to get the door of the king palace camel tender book of the year, the books detailed record of every fan portal belongs to the palace and type. Moreover, although apart inside and outside the palace, but he was ready to own a portable portal, it can be transferred to their own hall at any one palace treasure hunt beginning and the end of any transfer out of the palace a palace. Xu whole palace out only once, and portable door can not be transferred between the palace. Fortunately, however, the use of indoor Palace Portal There is no limit, each palace can make multiple entries.

Henry has now opened the door portability, choose a house that is about to enter. To do more to get the treasure, he hoped to arrange a route through the palace different treasure as much as possible. Please tell Henry that route passing through the largest number of different treasure palace.

Input Format

The first row gives the input file sotomon.in three positive integer N, R, C.

The following N rows, each row gives an information portal, comprising three positive integers xi, yi, of Ti, indicating that the transfer gate provided in the first row located at xi and yi treasure palace column type is Ti. Ti is an integer of 1 to 3, and 1 represents may be transmitted to the second xi row of any one of the "cross-day door", 2 represents transferred to the "vertical atlas door" arbitrary row yi-column, 3 represents around can be transmitted to 8 grid palace of "any door."

Ensure 1≤xi≤R, 1≤yi≤C, all portal position different from each other.

Output Format

Output file sotomon.out only a positive integer representing the maximum number of different treasure palace determine your route passes.

Sample input and output

Input # 1
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
Output # 1
9

Description / Tips

Data scale and conventions:

--------------------------------------------split line---- -------------------------------------------

At first glance, ordinary title search, thinking fifty-six very easy to get, and then like a pruning shears

But this extremely disgusting to see the range of data, 10 ^ 6, a matrix can save any

Made, a simple tarjan + DP

But think about the connection side seems a bit much

Then we can optimize (point which is also the most difficult subject, I tune a night) the construction side

 

Since then the particularity of each door, we should build a separate drawing, which is three algorithms for cross Tianmen each line, we will build it into a ring for each vertical column atlas door, and we will build it into a ring. Because we know:

All doors days between each horizontal row to each other are certainly accessible, and among all the doors of each column atlas longitudinal certainly are mutually accessible. So we can say:

When you reach a cross day door of a row when you reach this line all cross Tianmen, when you reach a vertical atlas door for a column when you reach this column all vertical atlas door.

So we can build it into a ring. The use of Tarjan came. We can use these two Tarjan ring shrunk to the point. For any door I did not expect violence to build than the side a better way, so he built violent side friends ~ ~ ~.

But if that was not enough, we have

SORT

We naturally hope to find a day cross the door when the sooner the better, so try to cross the sky in front of the door, so cmp is as follows:

bool cmp1(node a,node b){
    if(a.x!=b.x)return a.x<b.x;
    if(a.opt==1)return 1;
    if(b.opt==1)return 0;
    return a.y<b.y;
}

So look for the door when the vertical atlas, too:

bool cmp2(node a,node b){
    if(a.y!=b.y)return a.y<b.y;
    if(a.opt==2)return 1;
    if(b.opt==2)return 0;
    return a.x<b.x;
}

Well, we have lined up order, the next step is even clever side, we have the first represents the first time each cycle to find, last represented on a

So, even side code:

sort(P+1,P+number+1,cmp1);
    first=last=1;
    for(int i=1;i<=number;i++){
        if(P[i].x!=P[i+1].x){
            if(first!=last)add(P[last].id,P[first].id);
            first=last=i+1;
        }
        else{
            if(P[last].opt==1)add(P[last].id,P[i+1].id);
            if(P[i+1].opt==1)last=i+1;
            if(P[first].opt!=1)last=first=i+1;
        }
    }

Vertical door too atlas

So the next step is any door (think of A Dream), which we use to store map

Of course, this is the players enjoy c ++, other languages ​​can use hash

Then the code is as follows:

for(int i=1;i<=number;i++){
        if(P[i].opt==3){
            for(int k=0;k<8;k++){
                int nx=P[i].x+dx[k],ny=P[i].y+dy[k];
                if(fh.count(pa(nx,ny)))
                  add(P[i].id,fh[pa(nx,ny)]);
            }
        }
    }

Well, the end of the construction side of the poor, then look for the ring with Tarjan

这个不用多说,直接上代码:

void Tarjan(int now){
    low[now]=dfn[now]=++deeth;res[now]=1;
    q[++top]=now;
    for(int i=head[now];i;i=nxt[i]){
        int y=ver[i];
        if(!dfn[y])Tarjan(y),low[now]=min(low[now],low[y]);
        else if(res[y])low[now]=min(low[now],dfn[y]);
    }
    if(dfn[now]==low[now]){
        color[now]=++sum;res[now]=0;
        while(q[top]!=now){
            size[sum]++;
            res[q[top]]=0;color[q[top--]]=sum;
        }
        size[sum]++;top--;
    }
}

那么最后就是一个简单的DP了:

void dfs(int now,int fa){
    if(dp[now]>size[now])return;
    dp[now]=size[now];
    for(int i=head1[now];i;i=nxt1[i]){
        int y=ver1[i];
        if(y==fa)continue;
        dfs(y,now);
        dp[now]=max(dp[now],dp[y]+size[now]);
    }
}

for(int i=1;i<=sum;i++){
        if(in[i]==0){
            dfs(i,0);ans=max(ans,dp[i]);
        }
    }

那么AC代码就是:

  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 #define pa pair<int,int>
  4 
  5 const int _=300002;
  6 int number,length,wide,first,last,size[_],dp[_],in[_];
  7 int ver[_*10],head[_*10],nxt[_*10],from[_*10],tot,ans=-1;
  8 int ver1[_*10],head1[_*10],nxt1[_*10],tot1;
  9 int dx[9]={-1,-1,-1,0,0,1,1,1},dy[9]={-1,0,1,-1,1,-1,0,1};
 10 int color[_],sum,low[_],dfn[_],q[_],top,deeth,res[_];
 11 struct node{int x,y,opt,id;}P[_];
 12 map<pa,int>fh;
 13 
 14 int read(){
 15     int s=0,w=1;char ch=getchar();
 16     while(ch<'0'||ch>'9')w=(ch=='-')?-1:1,ch=getchar();
 17     while(ch>='0'&&ch<='9')s=s*10+ch-'0',ch=getchar();
 18     return s*w;
 19 }
 20 
 21 void add(int x,int y){
 22     from[++tot]=x;ver[tot]=y;nxt[tot]=head[x];head[x]=tot;
 23 }
 24 
 25 void ad(int x,int y){
 26     ver1[++tot1]=y;nxt1[tot1]=head1[x];head1[x]=tot1;
 27 }
 28 
 29 bool cmp1(node a,node b){
 30     if(a.x!=b.x)return a.x<b.x;
 31     if(a.opt==1)return 1;
 32     if(b.opt==1)return 0;
 33     return a.y<b.y;
 34 }
 35 
 36 bool cmp2(node a,node b){
 37     if(a.y!=b.y)return a.y<b.y;
 38     if(a.opt==2)return 1;
 39     if(b.opt==2)return 0;
 40     return a.x<b.x;
 41 }
 42 
 43 void Tarjan(int now){
 44     low[now]=dfn[now]=++deeth;res[now]=1;
 45     q[++top]=now;
 46     for(int i=head[now];i;i=nxt[i]){
 47         int y=ver[i];
 48         if(!dfn[y])Tarjan(y),low[now]=min(low[now],low[y]);
 49         else if(res[y])low[now]=min(low[now],dfn[y]);
 50     }
 51     if(dfn[now]==low[now]){
 52         color[now]=++sum;res[now]=0;
 53         while(q[top]!=now){
 54             size[sum]++;
 55             res[q[top]]=0;color[q[top--]]=sum;
 56         }
 57         size[sum]++;top--;
 58     }
 59 }
 60 
 61 void dfs(int now,int fa){
 62     if(dp[now]>size[now])return;
 63     dp[now]=size[now];
 64     for(int i=head1[now];i;i=nxt1[i]){
 65         int y=ver1[i];
 66         if(y==fa)continue;
 67         dfs(y,now);
 68         dp[now]=max(dp[now],dp[y]+size[now]);
 69     }
 70 }
 71 
 72 int main(){
 73 //    freopen("precious.in","r",stdin);
 74 //    freopen("precious.out","w",stdout);
 75     number=read();length=read();wide=read();
 76     for(int i=1;i<=number;i++){
 77         P[i].x=read();P[i].y=read();P[i].opt=read();P[i].id=i;
 78         fh[pa(P[i].x,P[i].y)]=i;
 79     }
 80     //-----------------------------------------------------
 81     for(int i=1;i<=number;i++){
 82         if(P[i].opt==3){
 83             for(int k=0;k<8;k++){
 84                 int nx=P[i].x+dx[k],ny=P[i].y+dy[k];
 85                 if(fh.count(pa(nx,ny)))
 86                   add(P[i].id,fh[pa(nx,ny)]);
 87             }
 88         }
 89     }
 90     //-----------------------------------------------------
 91     sort(P+1,P+number+1,cmp1);
 92     first=last=1;
 93     for(int i=1;i<=number;i++){
 94         if(P[i].x!=P[i+1].x){
 95             if(first!=last)add(P[last].id,P[first].id);
 96             first=last=i+1;
 97         }
 98         else{
 99             if(P[last].opt==1)add(P[last].id,P[i+1].id);
100             if(P[i+1].opt==1)last=i+1;
101             if(P[first].opt!=1)last=first=i+1;
102         }
103     }
104     //------------------------------------------------------
105     sort(P+1,P+number+1,cmp2);
106     first=last=1;
107     for(int i=1;i<=number;i++){
108         if(P[i].y!=P[i+1].y){
109             if(first!=last)add(P[last].id,P[first].id);
110             first=last=i+1;
111         }
112         else{
113             if(P[last].opt==2)add(P[last].id,P[i+1].id);
114             if(P[i+1].opt==2)last=i+1;
115             if(P[first].opt!=2)last=first=i+1;
116         }
117     }
118     //------------------------------------------------------
119     for(int i=1;i<=number;i++)
120        if(!dfn[i])Tarjan(i);
121     for(int i=1;i<=tot;i++){
122         int x=from[i],y=ver[i];
123         if(color[x]==color[y])continue;
124         ad(color[x],color[y]);in[color[y]]++;
125     }
126     for(int i=1;i<=sum;i++){
127         if(in[i]==0){
128             dfs(i,0);ans=max(ans,dp[i]);
129         }
130     }
131     cout<<ans;
132     return 0;
133 }

 

Guess you like

Origin www.cnblogs.com/GMSD/p/11616346.html