題目描述 在寬廣的非洲荒漠中,生活著一群勤勞勇敢的羊駝家族。被族人恭稱為“先知”的Alpaca L. Sotomon是這個家族的領袖,外人也稱其為“所駝門王”。所駝門王畢生致力于維護家族的安定與和諧,他曾親自率軍粉碎河蟹帝國主義的野蠻侵略,為族人立下赫赫戰功。所駝門王一生財寶無數,但因其生性節儉低調,他將財寶埋藏在自己設計的地下宮殿里,這也是今天Henry Curtis故事的起點。Henry是一個愛財如命的貪婪家伙,而又非常聰明,他費盡心機謀劃了這次盜竊行動,破解重重機關后來到這座地下宮殿前。
整座宮殿呈矩陣狀,由R×C間矩形宮室組成,其中有N間宮室里埋藏著寶藏,稱作藏寶宮室。宮殿里外、相鄰宮室間都由堅硬的實體墻阻隔,由一間宮室到達另一間只能通過所駝門王獨創的移動方式——傳送門。所駝門王為這N間藏寶宮室每間都架設了一扇傳送門,沒有寶藏的宮室不設傳送門,所有的宮室傳送門分為三種:
“橫天門”:由該門可以傳送到同行的任一宮室;“縱寰門”:由該門可以傳送到同列的任一宮室;
“自*河蟹*由*河蟹*門”:由該門可以傳送到以該門所在宮室為中心周圍8格中任一宮室(如果目標宮室存在的話)。
深謀遠慮的Henry當然事先就搞到了所駝門王當年的宮殿招標冊,書冊上詳細記錄了每扇傳送門所屬宮室及類型。而且,雖然宮殿內外相隔,但他自行準備了一種便攜式傳送門,可將自己傳送到殿內任意一間宮室開始尋寶,并在任意一間宮室結束后傳送出宮。整座宮殿只許進出一次,且便攜門無法進行宮室之間的傳送。不過好在宮室內傳送門的使用沒有次數限制,每間宮室也可以多次出入。
現在Henry已經打開了便攜門,即將選擇一間宮室進入。為得到盡多寶藏,他希望安排一條路線,使走過的不同藏寶宮室盡可能多。請你告訴Henry這條路線最多行經不同藏寶宮室的數目。 輸入輸出格式 輸入格式:
輸入文件sotomon.in 第一行給出三個正整數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,所有的傳送門位置互不相同。
輸出格式: 輸出文件sotomon.out只有一個正整數,表示你確定的路線所經過不同藏寶宮室的最大數目。
輸入樣例#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
輸出樣例#1: 9
題解 和洛谷的縮點模板題簡直不要一樣。。。。 首先考慮建邊,我暴力建邊然后就過了??? 用vector存一下每一行每一列的點 然后map儲存一下點的位置 對于每一種門,暴力連上邊 恩,解決完了連邊 剩下的很簡單啦 Tarjan縮點 然后重新連邊 用一個虛擬點作為源點 跑SPFA最長路就可以啦
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<set>
#include<map>
#include<vector>
#include<queue>
using namespace std;
#define MAX 110000
#define MAXL 5000050
#define INF 1000000000
inline int read()
{int x=0,t=1;char ch=getchar();while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();if(ch=='-')t=-1,ch=getchar();while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();return x*t;
}
struct Node
{int x,y;
};
inline bool operator <(Node a,Node b)
{if(a.x!=b.x)return a.x<b.x;else return a.y<b.y;
}
struct Line
{int v,next;
}e[MAXL];
struct Line2
{int v,next,w;
}ee[MAXL];
int H[MAX],cnt2=1;
inline void Add(int u,int v,int w)
{ee[cnt2]=(Line2){v,H[u],w};H[u]=cnt2++;
}
int N,M;
int h[MAX],cnt=1;
int w[MAX],dis[MAX],ans;
int xx[MAX],yy[MAX],tt[MAX];
inline void Add(int u,int v)
{e[cnt]=(Line){v,h[u]};h[u]=cnt++;
}
int tim,S[MAX],top;
bool vis[MAX];
int W[MAX],G[MAX];
int dfn[MAX],low[MAX],group;
vector<int> X[MAX],Y[MAX];
map<Node,int> qt;
int d[8][2]={1,0,0,1,-1,0,0,-1,1,1,1,-1,-1,1,-1,-1};
void Tarjan(int u)
{dfn[u]=low[u]=++tim;vis[u]=true;S[++top]=u;for(int i=h[u];i;i=e[i].next){int v=e[i].v;if(!dfn[v]){Tarjan(v);low[u]=min(low[u],low[v]);}elseif(vis[v])low[u]=min(low[u],dfn[v]);}if(low[u]==dfn[u]){++group;int v;do{v=S[top--];W[group]++;G[v]=group;vis[v]=false;}while(v!=u);}
}
int main()
{N=read();read();read();for(int i=1;i<=N;++i){xx[i]=read();yy[i]=read();tt[i]=read();X[xx[i]].push_back(i);Y[yy[i]].push_back(i);qt[(Node){xx[i],yy[i]}]=i;}for(int i=1;i<=N;++i){if(tt[i]==1){for(int j=0,l=X[xx[i]].size();j<l;++j)Add(i,X[xx[i]][j]);}else if(tt[i]==2){for(int j=0,l=Y[yy[i]].size();j<l;++j)Add(i,Y[yy[i]][j]);}else{for(int j=0;j<8;++j){int xxx=xx[i]+d[j][0];int yyy=yy[i]+d[j][1];Node uuu=(Node){xxx,yyy};if(qt.find(uuu)!=qt.end())Add(i,qt[uuu]);}}}for(int i=1;i<=N;++i)if(!dfn[i])Tarjan(i);for(int u=1;u<=N;++u){for(int i=h[u];i;i=e[i].next){int v=e[i].v;if(G[u]!=G[v])Add(G[u],G[v],W[G[v]]);}}for(int i=1;i<=group;++i)Add(0,i,W[i]);queue<int> Q;while(!Q.empty())Q.pop();int ans=0;memset(vis,0,sizeof(vis));Q.push(0);vis[0]=true;while(!Q.empty()){int u=Q.front();Q.pop();for(int i=H[u];i;i=ee[i].next){int v=ee[i].v,w=ee[i].w;if(dis[v]<dis[u]+w){dis[v]=dis[u]+w;ans=max(ans,dis[v]);if(!vis[v]){vis[v]=true;Q.push(v);}}}vis[u]=false;}printf("%d\n",ans);return 0;
}
轉載于:https://www.cnblogs.com/cjyyb/p/7623972.html
總結
以上是生活随笔 為你收集整理的【BZOJ1924】【SDOI2010】所驼门王的宝藏(Tarjan,SPFA) 的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔 網站內容還不錯,歡迎將生活随笔 推薦給好友。