在寬廣的非洲荒漠中,生活著一群勤勞勇敢的羊駝家族。被族人恭稱為「先知」的alpaca l. sotomon是這個家族的領袖,外人也稱其為「所駝門王」。所駝門王畢生致力於維護家族的安定與和諧,他曾親自率軍粉碎河蟹帝國主義的野蠻侵略,為族人立下赫赫戰功。所駝門王一生財寶無數,但因其生性節儉低調,他將財寶埋藏在自己設計的地下宮殿裡,這也是今天henry curtis故事的起點。henry是乙個愛財如命的貪婪傢伙,而又非常聰明,他費盡心機謀劃了這次盜竊行動,破解重重機關後來到這座地下宮殿前。
整座宮殿呈矩陣狀,由r×c間矩形宮室組成,其中有n間宮室裡埋藏著寶藏,稱作藏寶宮室。宮殿裡外、相鄰宮室間都由堅硬的實體牆阻隔,由一間宮室到達另一間只能通過所駝門王獨創的移動方式——傳送門。所駝門王為這n間藏寶宮室每間都架設了一扇傳送門,沒有寶藏的宮室不設傳送門,所有的宮室傳送門分為三種:
「橫天門」:由該門可以傳送到同行的任一宮室;
「縱寰門」:由該門可以傳送到同列的任一宮室;
「九宮門」:由該門可以傳送到以該門所在宮室為中心周圍8格中任一宮室(如果目標宮室存在的話)。
深謀遠慮的henry當然事先就搞到了所駝門王當年的宮殿招標冊,書冊上詳細記錄了每扇傳送門所屬宮室及型別。而且,雖然宮殿內外相隔,但他自行準備了一種可攜式傳送門,可將自己傳送到殿內任意一間宮室開始尋寶,並在任意一間宮室結束後傳送出宮。整座宮殿只許進出一次,且便攜門無法進行宮室之間的傳送。不過好在宮室內傳送門的使用沒有次數限制,每間宮室也可以多次出入。
現在henry已經開啟了便攜門,即將選擇一間宮室進入。為得到盡多寶藏,他希望安排一條路線,使走過的不同藏寶宮室盡可能多。請你告訴henry這條路線最多行經不同藏寶宮室的數目。
以下n行,每行給出一扇傳送門的資訊,包含三個正整數xi, yi, ti,表示該傳送門設在位於第xi行第yi列的藏寶宮室,型別為ti。ti是乙個1~3間的整數,1表示可以傳送到第xi行任意一列的「橫天門」,2表示可以傳送到任意一行第yi列的「縱寰門」,3表示可以傳送到周圍8格宮室的「九宮門」。
保證1≤xi≤r,1≤yi≤c,所有的傳送門位置互不相同。
只有乙個正整數,表示你確定的路線所經過不同藏寶宮室的最大數目。
資料規模和約定:
對於\(100\%\)的資料, \(n\leq 100,000,r\leq 1,000,000,c\leq 1,000,000\)。
一眼 \(tarjan\) 縮點拓撲求最長路。
然而如果直接暴力建邊的話會\(t\)上天,因為這題要建的邊賊多,比如說一行全是橫門,暴力建邊是兩兩之間都建的,最壞複雜度 \(o(n^2)\)。
考慮優化建圖。
觀察到一行的橫門或者一列的縱門一定是在同乙個連通分量裡的,所以我們對於同一行的橫門或者同一行的縱門就沒必要兩兩連邊了,保證直接連成乙個環就好了。
但是如果一行中有很多橫門,同時也有很多其他的門,那麼還是會每個橫門向每個別的種類的門連邊,邊數還是太多。
但是因為一行中的橫門是乙個環,所以對於一行中的其它宮室,只需從環上向這個宮室連一條邊就夠了。
於是得到了下面成型的演算法思路:
我們對於每一行的橫門,每一列的縱門,還有九宮門分開建圖。
第一遍建出橫門向外連的所有邊。第二遍建出縱門向外連的所有邊。第三遍建出九宮門向外連的所有邊。
我們模擬第一次建邊。
因為要優化建邊過程的複雜度,我們想盡可能的先迴圈到橫門,所以可以先排序一遍,這樣的話如果當前不是橫門就可以直接 \(break\) 掉了。
對於所有宮室,我們按照行數排序,保證一行上的所有宮室都會一塊迴圈到。如果行數相同,那麼我們優先將橫門排在前面。
對於迴圈到的每一行的第乙個橫門,我們將其記為 \(first\),同時規定 \(last\) 變數是上乙個掃到的橫門。
然後開始掃這一行的宮室。
如果當前宮室是橫門,那麼 \(add(last,now)\),同時令 \(last=now\)。
否則,\(add(last,now)\)。
最後,\(add(last,first)\)。
這就完成了一行的掃瞄。
縱門也是同理。
對於九宮門,我沒有想出太好的建邊方案,於是直接暴力列舉每個九宮門周圍的八個格仔是否有寶藏。這裡可以用 \(stl\) 的 \(map\) 來儲存每個點是否有寶藏,但是我這裡因為害怕被卡常,手寫了個 \(hash\) 表。
其它就沒什麼了。
我還毒瘤的加上了fread快讀
#include#include#include#include#define n 100005
#define mod 10007
#define ll long long
#define min(a,b) ((a)<(b)?(a):(b))
#define max(a,b) ((a)>(b)?(a):(b))
int x,n,m;
bool in[n];
int cnt,tot,sum;
int head2[n],deg[n];
std::queuetopo;
int stk[n],top,dis[n];
int head[n],belong[n];
int dfn[n],low[n],sze[n];
int hshhead[mod+2],hshcnt;
int dx=;
int dy=;
struct edgeedge[n<<3],edge2[n<<3];
struct hashh[n<<2];
void hshadd(ll x,ll z,int i)
struct nodetype[n];
bool cmp1(node x,node y)
bool cmp2(node x,node y)
void add(int x,int y)
void add2(int x,int y)
inline char nc()
//#define nc getchar
inline int getint()
void tarjan(int now)
else if(in[to])
low[now]=min(low[now],dfn[to]);
}if(low[now]==dfn[now])while(y!=now);
}}void hash()
}int hsh(ll q)
return 0;
}signed main()
hash();
std::sort(type+1,type+1+x,cmp1);
for(int i=1;i<=x;i++)
add(last,type[j].id);
last=type[j].id;
}else add(type[i].id,type[j].id);
}if(last!=fist)
add(last,fist);
i=fina;}}
std::sort(type+1,type+1+x,cmp2);
for(int i=1;i<=x;i++)
add(last,type[j].id);
last=type[j].id;
}else add(type[i].id,type[j].id);
}if(last!=fist)
add(last,fist);
i=fina;}}
for(int i=1;i<=x;i++)
}
for(int i=1;i<=x;i++)
cnt=0;
for(int i=1;i<=x;i++)
}int ans=0;
for(int i=1;i<=tot;i++)
}while(topo.size())
}printf("%d\n",ans);
return 0;
}
SDOI2010 所駝門王的寶藏
題面 題解我寫的是讓同一行 同一列的點形成乙個環,表示它們互相可達。aysn 寫的是對於同一行列建乙個新點表示互相可達。看了窩還是太弱了,還須多練。include include include include include include include include define ri re...
P2403 SDOI2010 所駝門王的寶藏
在寬廣的非洲荒漠中,生活著一群勤勞勇敢的羊駝家族。被族人恭稱為 先知 的alpaca l.sotomon是這個家族的領袖,外人也稱其為 所駝門王 所駝門王畢生致力於維護家族的安定與和諧,他曾親自率軍粉碎河蟹帝國主義的野蠻侵略,為族人立下赫赫戰功。所駝門王一生財寶無數,但因其生性節儉低調,他將財寶埋藏...
bzoj 1924 所駝門王的寶藏
題目大意 有乙個r c的矩陣,上面有n個點有寶藏 每個有寶藏的點上都有傳送門 傳送門有三種 第一種可以傳到該行任意乙個有寶藏的點,第二種可以傳到該列任意乙個有寶藏的點,第三種可以傳到周圍的八連塊上有寶藏的點 現在你可以在任意乙個有寶藏的點開始,求你最多可以經過多少個不同的藏寶點 每個藏寶點可以多次進...