洛谷2403 [SDOI2010]所駝門王的寶藏
題目描述
在寬廣的非洲荒漠中,生活著一群勤勞勇敢的羊駝家族。被族人恭稱為“先知”的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
說明
數據規模和約定:
題解:
建圖,縮點,然後跑最長路。T了很久,後來發現自己確實太暴力了。如果暴力建圖,同一行或列之間連邊可能會爆,同一行傳送門類型都為1的點最後一定是一個連通分量,
所以可以直接連成一個環,再從這個環上任意一個點向同行的其它點連邊,穿傳送門類型為2的同理。跑最長路的時候,我跑了n遍spfa,然後學到了DAG上可以拓撲排序+DP
找起點終點不定的最長路,dp[i]表示以i結束的最長路的長度,按照拓撲序更新,這樣用i去更新其它點時,可以保證i已經最優了,避免重復更新。
#include<bits/stdc++.h> #define nn 2000010 #define mm 4000010 #define inf -100000000 using namespace std; map<pair<int,int>,int> fi; pair<int,int> in; int xi[8]={-1,-1,-1,0,0,1,1,1},yi[8]={-1,0,1,-1,1,-1,0,1}; int x[nn],y[nn]; int fir[nn<<1],nxt[mm<<1],to[mm<<1],ti[nn],li[nn],rep[nn],sta[nn],mo[nn<<1],dis[nn<<1],q[nn<<1],du[nn<<1]; bool vis[nn<<1]; int e=0,l=0,t=0,ne,h; int read() { int ans=0,f=1;char ch=getchar(); while(!isdigit(ch)) {if(ch==‘-‘) f=-1;ch=getchar();} while(isdigit(ch)) {ans=ans*10+ch-‘0‘;ch=getchar();} return ans*f; } void add(int u,int v) { nxt[++e]=fir[u];fir[u]=e;to[e]=v; } int cmp1(int a,int b) { if(x[a]==x[b]) return ti[a]<ti[b]; return x[a]<x[b]; } int cmp2(int a,int b) { if(y[a]==y[b]) return ti[a]<ti[b]; return y[a]<y[b]; } void tarjan(int now) { int sum=1; vis[now]=1; ti[now]=li[now]=++l;sta[++t]=now; for(int i=fir[now];i;i=nxt[i]) if(!ti[to[i]]) //// { tarjan(to[i]); li[now]=min(li[now],li[to[i]]); } else if(vis[to[i]]&&li[now]>ti[to[i]]) //// li[now]=ti[to[i]]; //// if(li[now]==ti[now]) { ne++; while(sta[t]!=now) { vis[sta[t]]=0; rep[sta[t]]=ne; sum++; t--; } mo[ne]=sum; rep[sta[t]]=ne; vis[sta[t]]=0;t--; } } int dp(int n) { int o,an=-1; while(h<=t) { o=q[h++]; if(dis[o]>an) an=dis[o]; for(int i=fir[o];i;i=nxt[i]) { du[to[i]]--; if(dis[to[i]]<dis[o]+mo[to[i]]) dis[to[i]]=dis[o]+mo[to[i]]; if(!du[to[i]]) q[++t]=to[i]; } } return an; } int main() { // freopen("o.txt","r",stdin); // freopen("o.out","w",stdout); int n=read(),r=read(),c=read(); ne=n; for(int i=1;i<=n;i++) { in.first=read();in.second=read(); x[i]=in.first;y[i]=in.second; ti[i]=read(); fi[in]=i; li[i]=i; } for(int i=1;i<=n;i++) if(ti[i]==3) for(int j=0;j<8;j++) { in.first=x[i]+xi[j]; in.second=y[i]+yi[j]; if(fi.find(in)!=fi.end()) add(i,fi[in]); } sort(li+1,li+n+1,cmp1); for(int i=1;i<=n;i++) { int fi=0,la=0,j; for(j=i;j<=n&&x[li[i]]==x[li[j]];j++) if(ti[li[j]]==1) { if(!fi) fi=j; la=j; if(fi!=la) add(li[j-1],li[j]); } if(fi) { if(fi!=la) add(li[la],li[fi]); for(j=i;j<=n&&x[li[i]]==x[li[j]];j++) if(ti[li[j]]!=1) add(li[la],li[j]); } i=j-1; } for(int i=1;i<=n;i++) li[i]=i; sort(li+1,li+n+1,cmp2); for(int i=1;i<=n;i++) { int fi=0,la=0,j; for(j=i;j<=n&&y[li[i]]==y[li[j]];j++) if(ti[li[j]]==2) { if(!fi) fi=j; la=j; if(fi!=la) add(li[j-1],li[j]); } if(fi) { if(fi!=la) add(li[la],li[fi]); for(j=i;j<=n&&y[li[i]]==y[li[j]];j++) if(ti[li[j]]!=2) add(li[la],li[j]); } i=j-1; } fill(ti,ti+n+1,0); fill(li,li+n+1,0); for(int i=1;i<=n;i++) if(!ti[i]) tarjan(i); for(int i=1;i<=n;i++) for(int j=fir[i];j;j=nxt[j]) if(rep[i]!=rep[to[j]]) { add(rep[i],rep[to[j]]); du[rep[to[j]]]++; } h=1,t=0; for(int i=n+1;i<=ne;i++) if(!du[i]) { q[++t]=i; dis[i]=mo[i]; } printf("%d",dp(n)); return 0; }
洛谷2403 [SDOI2010]所駝門王的寶藏