尋找道路——呆滯大佬der最騷暴力
尋找道路
題目描述:
有點的出邊所指向的點都直接或間接與終點連通。
2 .在滿足條件1 的情況下使路徑最短。
註意:圖G 中可能存在重邊和自環,題目保證終點沒有出邊。
請你輸出符合條件的路徑的長度。
輸入格式:
第一行有兩個用一個空格隔開的整數n 和m ,表示圖有n 個點和m 條邊。
接下來的m 行每行2 個整數x 、y ,之間用一個空格隔開,表示有一條邊從點x 指向點y 。
最後一行有兩個用一個空格隔開的整數s 、t ,表示起點為s ,終點為t 。
輸出格式:
輸出只有一行,包含一個整數,表示滿足題目?述的最短路徑的長度。如果這樣的路徑不存在,輸出- 1 。
樣例輸入:
樣例1: 3 2 1 2 2 1 1 3 樣例2: 6 6 1 2 1 3 2 6 2 5 4 5 3 4 1 5
樣例輸出:
樣例1: -1 樣例2: 3
提示:
解釋1:
如上圖所示,箭頭表示有向道路,圓點表示城市。起點1 與終點3 不連通,所以滿足題
目?述的路徑不存在,故輸出- 1 。
解釋2:
如上圖所示,滿足條件的路徑為1 - >3- >4- >5。註意點2 不能在答案路徑中,因為點2連了一條邊到點6 ,而點6 不與終點5 連通。
對於30%的數據,0
對於60%的數據,0
對於100%的數據,0
時間限制:1000ms
空間限制:256MByte
來源:NOIP2014提高t5
俗話說的好啊,現有搜索後有天,反向剪枝日神仙。這題在網上的題解十分多我看了一下,有用棧優化bellman-ford,SPFA,Dijkstra+heap,bellman-ford+stack等等等等,這些我都聽不懂。呆滯大佬說,我只要兩次bfs就可以搞定。關於程序中詭異的ti數組和a結構體,詳見《聯合權值——呆滯大佬der最騷操作?》
http://www.cnblogs.com/cain-/p/7306003.html
#include<bits/stdc++.h> #include<bits/stdc++.h> using namespace std; struct nob{ int sta,ed; }a[200005]; bool mmp(nob a,nob b){ return a.ed<b.ed; } int n,m,has[100005]={0},has1[100005]={0},s[1000001]={0},ti[200005]={0},start,finish,step[200005]={0}; int main(){ cin>>n>>m; for (int i=1; i<=m; i++){ cin>>a[i].sta>>a[i].ed; ti[a[i].ed]++; }//這裏是不是覺得有點奇怪 for (int i=1; i<=n; i++) ti[i]+=ti[i-1]; cin>>start>>finish; sort(a+1,a+1+m,mmp); int head=0,tail=1; s[1]=finish;//從尾巴開始找 has[finish]=1; while (head<tail){ head++; for (int i=ti[s[head]-1]+1; i<=ti[s[head]]; i++){ if (has[a[i].sta]==0){ has[a[i].sta]=1; tail++; s[tail]=a[i].sta; } } }//找出不能到達的點 for (int i=1; i<=n; i++){ if (has[i]==0){ has1[i]=1; for (int l=ti[i-1]+1; l<=ti[i]; l++){ has1[a[l].sta]=1; } } }//用不能到達的點來反向標記他的父親,表示父親節點有子節點沒有直接或間接地指向終點 head=0;tail=1; s[1]=finish; has1[finish]=1; while (head<tail){ head++; if (s[head]==start){ cout<<step[s[head]]; return 0; } for (int i=ti[s[head]-1]+1; i<=ti[s[head]]; i++){ if (has1[a[i].sta]==0){ has1[a[i].sta]=1; tail++; s[tail]=a[i].sta; step[a[i].sta]=step[a[i].ed]+1; } } }//再次廣搜找出答案 cout<<-1; return 0; }
參考了聯合權值那道題目之後你會發現這個有些奇怪,那就對了,這就是傳說中最難以預判的剪枝,倒搜剪枝!用正著搜索的話即使用同樣的方法還是過不了的,然後我們再來仔細地研究一下這個代碼,就會發現這裏用了兩次廣搜,第一次廣搜看上去是將能夠到達的點標記,實質上是遍歷has數組將不能到達的點找出來,找到不能到達的點之後再在has1數組中將他的父親節點和他自己標記起來表示這些點不能走。然後就可以完成這道題目啦。
尋找道路——呆滯大佬der最騷暴力