NOIp1996提升組第三題ios
在一個地圖上有N個地窖(N≤20),每一個地窖中埋有必定數量的地雷。同時,給出地窖之間的鏈接路徑。當地窖及其鏈接的數據給出以後,某人能夠從任一處開始挖地雷,而後能夠沿着指出的鏈接往下挖(僅能選擇一條路徑),當無鏈接時挖地雷工做結束。設計一個挖地雷的方案,使某人能挖到最多的地雷。c++
有若干行。git
第1行只有一個數字,表示地窖的個數N。數組
第2行有N個數,分別表示每一個地窖中的地雷個數。函數
第3行至第N+1行表示地窖之間的鏈接狀況:ui
第3行有n-1個數(0或1),表示第一個地窖至第2個、第3個、…、第n個地窖有否路徑鏈接。如第3行爲011000…0,則表示第1個地窖至第2個地窖有路徑,至第3個地窖有路徑,至第4個地窖、第5個、…、第n個地窖沒有路徑。spa
第4行有n−2個數,表示第二個地窖至第3個、第4個、…、第n個地窖有否路徑鏈接。設計
… …code
第n+1行有1個數,表示第n−1個地窖至第n個地窖有否路徑鏈接。(爲0表示沒有路徑,爲1表示有路徑)。blog
有兩行
第一行表示挖得最多地雷時的挖地雷的順序,各地窖序號間以一個空格分隔,不得有多餘的空格。
第二行只有一個數,表示能挖到的最多地雷數。
5
10 8 4 7 6
1 1 1 0
0 0 0
1 1
1
1 3 4 5
27
(1)dfs的內心路程就是定義一個bool型函數判斷它還能不能挖,dfs函數部分判斷若是不能繼續挖下去,而且挖到的地雷數比以前的還多,就用opt記錄路徑pre,若是還能挖下去,就for循環找下一個能挖的地方,而後b改變標記,繼續dfs,注意回溯b的標記。(碼風可能有些奇怪
#include"bits/stdc++.h" using namespace std; inline int read() { int num=0,f=1; char c=getchar(); for(; !isdigit(c); c=getchar()) if(c=='-') f=-1; for(; isdigit(c); c=getchar()) num=num*10+c-'0'; return num*f; } int n; int ans=0; #define N 22 int a[N]; int mp[N][N]; #define INF 0x3f3f3f3f int pre[N]; bool b[N]; int cnt; int opt[N]; int print(int x) { if(!pre[x]) cout<<pre[x]<<' '; else print(pre[x]); } bool check(int x) { for(int i=1; i<=n; i++) if(mp[x][i] && !b[i]) return false; return true; } void dfs(int x,int step,int sum) { if(check(x)) { if(sum>ans) { ans=sum; cnt=step; for(int i=1; i<=step; i++) opt[i]=pre[i]; } return ; } for(int i=1; i<=n; i++) { if(!b[i] && mp[x][i]) { b[i]=1; pre[step+1]=i; dfs(i,step+1,sum+a[i]); b[i]=0; } } } void init() { for(int i=1; i<=n; i++) pre[i]=0; for(int i=1; i<=n; i++) b[i]=false; } int main() { n=read(); init(); for(int i=1; i<=n; i++) a[i]=read(); for(int i=1; i<=n-1; i++) { for(int j=i+1; j<=n; j++) { cin>>mp[i][j]; } } for(int i=1; i<=n; i++) { b[i]=1; pre[1]=i; dfs(i,1,a[i]); b[i]=0; } for(int i=1; i<=cnt; i++) cout<<opt[i]<<' '; cout<<endl<<ans; return 0; }
(2)dp的內心路程是逆推,狀態轉移方程是f[i]=max{f[j]+h[i]}(mp[i][j]=1,i<j<=n)。
#include<stack> #include<queue> #include<algorithm> #include<cmath> #include<set> #include<map> #include<cctype> #include<list> #include<iostream> #include<cstdio> #include<cstring> #define N 222 using namespace std; int n; int mp[N][N]; int h[N]; int f[N]; int ans=0; int k=0; int a[N]; inline int read() { int num=0,f=1; char c=getchar(); for(; !isdigit(c); c=getchar()) if(c=='-') f=-1; for(; isdigit(c); c=getchar()) num=num*10+c-'0'; return num*f; } int main() { /* freopen("lei.in","r",stdin); freopen("lei.out","w",stdout);*/ n=read(); for(int i=1; i<=n; i++) cin>>h[i],f[i]=h[i]; int x,y; /* while(scanf("%d",&x)!=0&&scanf("%d",&y)!=0) { mp[x][y]=1; }*/ for(int i=1; i<=n; i++) for(int j=i+1; j<=n; j++) { int ww; cin>>ww; if(ww==1) mp[i][j]=1; } a[n]=0; for(int i=n-1; i>0; i--) for(int j=i+1; j<=n; j++) if(mp[i][j]&&f[j]+h[i]>f[i]) { f[i]=f[j]+h[i]; a[i]=j; } for(int i=1; i<=n; i++) if(ans<f[i]) { ans=f[i]; k=i; } cout<<k; k=a[k]; while(k) { cout<<" "<<k; k=a[k]; } cout<<"\n"<<ans<<'\n'; return 0; }
一年一度的「跳石頭」比賽又要開始了!
這項比賽將在一條筆直的河道中進行,河道中分佈着一些巨大岩石。組委會已經選擇好了兩塊岩石做爲比賽起點和終點。在起點和終點之間,有 N 塊岩石(不含起點和終點的岩石)。在比勝過程中,選手們將從起點出發,每一步跳向相鄰的岩石,直至到達終點。
爲了提升比賽難度,組委會計劃移走一些岩石,使得選手們在比勝過程中的最短跳躍距離儘量長。因爲預算限制,組委會至多從起點和終點之間移走 M 塊岩石(不能移走起點和終點的岩石)。
第一行包含三個整數L,N,M,分別表示起點到終點的距離,起點和終點之間的岩石數,以及組委會至多移走的岩石數。保證 \(L \geq 1\) 且 \(N \geq M \geq 0\)。
接下來 N 行,每行一個整數,第 i 行的整數\(D_i( 0 < D_i < L)\), 表示第i塊岩石與起點的距離。這些岩石按與起點距離從小到大的順序給出,且不會有兩個岩石出如今同一個位置。
一個整數,即最短跳躍距離的最大值。
25 5 2
2
11
14
17
21
4
輸入輸出樣例1說明:將與起點距離爲2和14的兩個岩石移走後,最短的跳躍距離爲 4(從與起點距離17的岩石跳到距離21的岩石,或者從距離21的岩石跳到終點)。
另:對於20%的數據,0 ≤ M ≤ N ≤ 10。
對於50%的數據,0 ≤ M ≤ N ≤ 100。
對於100%的數據,0 ≤ M ≤ N ≤ 50,000,1 ≤ L ≤ 1,000,000,000。
這道題用到了小a學長講的二分答案。
因而,在這裏獻醜啦。總結一下二分答案:
- 求最大的最小值
- 求最小的最大值
- 求知足條件下的最大(最小)值
- 求最靠近一個值的值
- 求最小的能知足條件的代價
附上一個接近萬能的二分模板:
int erfen(int x){ int l=1,r=maxn,ans=0; while(l<=r){ int mid=(l+r) >> 1; if(check(mid)) ans=mid,l=mid+1; else r=mid-1; } return ans; }
再附上一位dalao的講解:
二分答案應該是在一個單調閉區間上進行的。也就是說,二分答案最後獲得的答案應該是一個肯定值,而不是像搜索那樣會出現多解。二分通常用來解決最優解問題。剛纔咱們說單調性,那麼這個單調性應該體如今哪裏呢?
能夠這樣想,在一個區間上,有不少數,這些數多是咱們這些問題的解,換句話說,這裏有不少不合法的解,也有不少合法的解。咱們只考慮合法解,並稱之爲可行解。考慮全部可行解,咱們確定是要從這些可行解中找到一個最好的做爲咱們的答案, 這個答案咱們稱之爲最優解。
最優解必定可行,但可行解不必定最優。咱們假設整個序列具備單調性,且一個數x爲可行解,那麼通常的,全部的x'(x'<x)都是可行解。而且,若是有一個數y是非法解,那麼通常的,全部的y'(y'>y)都是非法解。
接下來code就很好搞啦~
值得注意的一點是,它終點也是有石頭的~
check函數判斷,詳見代碼啦~
#include<iostream> #include<cstdio> #include<cstring> #include<stack> #include<queue> #include<algorithm> #include<cmath> #include<set> #include<map> #include<cctype> #include<list> #define M 100099 #define INF 0x3f3f3f3f using namespace std; long long int dis; int n,m; int c[M]; int minn=INF; int maxn=-INF; int ans=0; inline int read() { int num=0,f=1; char c=getchar(); for(; !isdigit(c); c=getchar()) if(c=='-') f=-1; for(; isdigit(c); c=getchar()) num=num*10+c-'0'; return num*f; } int check(int x) {//爲何要用二分,由於具備單調性而且有界(騷~ int num=0,now=0;//num已經搬走的,now目前的 for(int i=1; i<=n+1; i++) {//要到終點那塊 if(c[i]-now<x) {//若是比當前枚舉的最小距離還小就搬走 num++; } else now=c[i]; } if(num>m) return 0;//超過題目要求的 } void erfen(int x,int y) { int l=0,r=dis; while(l<=r) { int mid=(l+r) >> 1; if(check(mid)) { l=mid+1; ans=mid; } else { r=mid-1; } } } int main() { /*freopen("stone.in","r",stdin); freopen("stone.out","w",stdout);*/ dis=read(); n=read(); m=read(); int l=0,r=dis; for(int i=1; i<=n; i++) cin>>c[i]; c[n+1]=dis; while(l<=r) { int mid=(l+r) >> 1; if(check(mid)) { l=mid+1; ans=mid; } else { r=mid-1; } } cout<<ans; }
春春是一名道路工程師,負責鋪設一條長度爲 n 的道路。
鋪設道路的主要工做是填平下陷的地表。整段道路能夠看做是 n 塊首尾相連的區域,一開始,第 i 塊區域下陷的深度爲 \(d_i\) 。
春春天天能夠選擇一段連續區間[L,R],填充這段區間中的每塊區域,讓其下陷深度減小 1。在選擇區間時,須要保證,區間內的每塊區域在填充前下陷深度均不爲 0 。
春春但願你能幫他設計一種方案,能夠在最短的時間內將整段道路的下陷深度都變爲 0 。
輸入文件包含兩行,第一行包含一個整數 n,表示道路的長度。 第二行包含 n 個整數,相鄰兩數間用一個空格隔開,第 i 個整數爲 \(d_i\)。
輸出文件僅包含一個整數,即最少須要多少天才能完成任務。
6
4 3 2 5 3 5
9
一種可行的最佳方案是,依次選擇: [1,6]、[1,6]、[1,2]、[1,1]、[4,6]、[4,4]、[4,4]、[6,6]、[6,6]。
對於 30% 的數據,1 ≤ n ≤ 10 ;
對於 70% 的數據,1 ≤ n ≤ 1000;
對於 100% 的數據,1 ≤ n ≤ 100000 , 0 ≤ \(d_i\) ≤ 10000。
這道題我竟然**似的沒看出來是原題(指積木大賽)(CCF:我抄我本身)。主要的內心路程仍是很善良的,主要的code也就是兩三行Q。咳咳,正經一點,兩種思路。
(1)貪心思路:若a[i]>a[i-1],計數器sum+=a[i]-a[i-1];
驗證:假設如今有一個坑,但旁邊又有一個坑。
你確定會選擇把兩個同時減1;
那麼小的坑確定會被大的坑「帶着」填掉。
大的坑也會減小a[i]-a[i-1]的深度,能夠說是「免費的」;
因此這樣貪心是對的;(來自dalao)
#include<bits/stdc++.h> using namespace std; int n,a[100005]; long long ans=0; int main() { cin>>n; for(int i=1;i<=n;i++) cin>>a[i]; for(int i=2;i<=n;i++) if(a[i]>a[i-1]) ans+=a[i]-a[i-1]; cout<<ans+a[1]; return 0; }
(2)遞推思路:
用f[i]表示前i個坑所鋪設的最少天數
那麼要作的只需比較一下當前的a[i](就是坑的深度)和a[i−1],分兩種狀況:
若是a[i]<=a[i-1],那麼在填a[i−1]時就能夠順便把a[i]填上,這樣顯然更優,因此f[i]=f[i-1];
不然的話,那麼在填a[i−1]時確定要儘可能把a[i]一塊填上,a[i]剩餘的就單獨填。。
因此,f[i]=f[i−1]+(a[i]−a[i−1])。
初始化f[1]=a[1],向後推就好了。(依舊來自dalao)
#include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> #include<iomanip> #include<stack> #include<queue> #include<map> #include<list> #include<set> #include<cctype> #include<bitset> #define N 100111 int n,opt[N],uxv[N]; inline int read() { int num=0,f=1; char c=getchar(); for(; !isdigit(c); c=getchar()) if(c=='-') f=-1; for(; isdigit(c); c=getchar()) num=num*10+c-'0'; return num*f; } int main(){ //freopen("road.in","r",stdin); freopen("road.out","w",stdout); n=read(); for(int i=1;i<=n;i++) uxv[i]=read(); opt[1]=uxv[1]; for(int i=2;i<=n;i++) uxv[i]<=uxv[i-1] ? opt[i]=opt[i-1] : opt[i]=opt[i-1]+(uxv[i]-uxv[i-1]); printf("%d",opt[n]); }
花匠棟棟種了一排花,每株花都有本身的高度。花兒越長越大,也愈來愈擠。棟棟決定把這排中的一部分花移走,將剩下的留在原地,使得剩下的花能有空間長大,同時,棟棟但願剩下的花排列得比較別緻。
具體而言,棟棟的花的高度能夠當作一列整數\(h_1\),\(h_2\),...,\(h_n\)。設當一部分花被移走後,剩下的花的高度依次爲\(g_1\),\(g_2\),...,\(g_m\),則棟棟但願下面兩個條件中至少有一個知足:
條件 A:對於全部\(g_{2i}\)>\(g_{2i-1}\),\(g_{2i}\)>\(g_{2i+1}\)
條件 B:對於全部\(g_{2i}\)<\(g_{2i-1}\),\(g_{2i}\)<\(g_{2i+1}\)
注意上面兩個條件在m=1時同時知足,當m>1時最多有一個能知足。
請問,棟棟最多能將多少株花留在原地。
第一行包含一個整數n,表示開始時花的株數。
第二行包含n個整數,依次爲\(h_1\),\(h_2\),...,\(h_n\),表示每株花的高度。
一個整數m,表示最多能留在原地的花的株數。
5
5 3 2 1 2
3
有多種方法能夠正好保留3株花,例如,留下第一、四、5株,高度分別爲五、一、2,知足條件 B。
對於 20%的數據,n ≤ 10;
對於 30%的數據,n ≤ 25;
對於 70%的數據,n ≤ 1000,0 ≤ \(h_i\)≤ 1000;
對於 100%的數據,1≤n≤100,000,0≤\(h_i\)≤1,000,000,全部的\(h_i\)隨機生成,全部隨機數服從某區間內的均勻分佈。
考前作luogu上DP的題,而後翻題解的時候看到個雙倍經驗(眼前一亮),發現那道題的雙倍經驗就是這道,可是當時只是看了看題目,以爲真的是雙倍經驗,而後默默點了加入任務計劃。(我:MMP??)
廢話很少bb,畫個圖來解釋???(充滿善意的微笑)
而後吶,就差很少是這個意思。要再也不來解釋下樣例??(好的,又一次)
好的,差很少就是這個樣子。
而後就很是的好理解了,讓你找一個最長的大波浪序列,記錄下波谷波峯就好啦。(這是dalao的想法,如下才是個人)用兩個數組分別記錄到i降低和到i上升。
這是dalao的代碼:
#include<bits/stdc++.h> using namespace std; int n,h[1000005],ans=1;bool con; int main() { cin>>n;for(int i=1;i<=n;i++) cin>>h[i]; if(h[2]>=h[1]) con=1; for(int i=1;i<=n;i++) { if(con==0&&i==n) {ans++;break;} if(con==1) if(h[i+1]<h[i]){ans++;con=0;continue;} if(con==0) if(h[i+1]>h[i]) {ans++;con=1;continue;} } cout<<ans; }
這是個人代碼:
#include<iostream> #include<cstdio> #include<cstring> #include<stack> #include<queue> #include<algorithm> #include<cmath> #include<set> #include<map> #include<cctype> #include<list> #define N 100055 using namespace std; int h[N],f[N][3]; inline int read() { int num=0,f=1; char c=getchar(); for(; !isdigit(c); c=getchar()) if(c=='-') f=-1; for(; isdigit(c); c=getchar()) num=num*10+c-'0'; return num*f; } int main() { /*freopen("flower.in","r",stdin); freopen("flower.out","w",stdin);*/ int n,ans=0; n=read(); memset(f,0,sizeof(f)); for(int i=1; i<=n; i++) { h[i]=read(); // f[i][0]=f[i][4]=1; } f[1][0]=f[1][5]=1; for(int i=2; i<=n; i++) { if(h[i]>h[i-1]) f[i][0]=f[i-1][6]+1; else f[i][0]=f[i-1][0]; if(h[i]<h[i-1]) f[i][7]=f[i-1][0]+1; else f[i][8]=f[i-1][9]; } ans=max(f[n][0],f[n][10]); cout<<ans<<endl; }
在網友的國度中共有 nn 種不一樣面額的貨幣,第 i 種貨幣的面額爲 a[i],你能夠假設每一種貨幣都有無窮多張。爲了方便,咱們把貨幣種數爲 n、面額數組爲 a[1..n] 的貨幣系統記做 (n,a)。
在一個完善的貨幣系統中,每個非負整數的金額 x 都應該能夠被表示出,即對每個非負整數 x,都存在 n 個非負整數 t[i] 知足 a[i] \times t[i]a[i]×t[i] 的和爲 xx。然而, 在網友的國度中,貨幣系統多是不完善的,便可能存在金額 xx 不能被該貨幣系統表示出。例如在貨幣系統 n=3n=3, a=[2,5,9]a=[2,5,9] 中,金額 1,31,3 就沒法被表示出來。
兩個貨幣系統 (n,a)(n,a) 和 (m,b)(m,b) 是等價的,當且僅當對於任意非負整數 xx,它要麼都可以被兩個貨幣系統表出,要麼不能被其中任何一個表出。
如今網友們打算簡化一下貨幣系統。他們但願找到一個貨幣系統 (m,b)(m,b),知足 (m,b)(m,b) 與原來的貨幣系統 (n,a)(n,a) 等價,且 mm 儘量的小。他們但願你來協助完成這個艱鉅的任務:找到最小的 mm。
輸入輸出格式
輸入格式:
輸入文件的第一行包含一個整數 TT,表示數據的組數。
接下來按照以下格式分別給出 TT 組數據。 每組數據的第一行包含一個正整數 nn。接下來一行包含 nn 個由空格隔開的正整數 a[i]a[i]。
輸出格式:
輸出文件共有 TT 行,對於每組數據,輸出一行一個正整數,表示全部與 (n,a)(n,a) 等價的貨幣系統 (m,b)(m,b) 中,最小的 mm。
輸入輸出樣例
輸入樣例#1:
2
4
3 19 10 6
5
11 29 13 19 17
輸出樣例#1:
2
5
在第一組數據中,貨幣系統(2,[3,10])和給出的貨幣系統(n,a)等價,並能夠驗證不存在 m < 2 的等價的貨幣系統,所以答案爲 22。
在第二組數據中,能夠驗證不存在 m < n 的等價的貨幣系統,所以答案爲 5。
[][11]
對於 100% 的數據,知足 1 ≤ T ≤ 20, n,a[i] ≥ 1。
考試時,題面我都沒搞懂,我是來搞笑的嘛Q?改題時:逐漸開始佩服我本身,仍是Orz一下咱們的loceaner大佬吧。
附上dalao的思路:
先解釋一下樣例1中第一組數據的3,10,19,6等價於3,10的緣由
6=3+3,19=3+3+3+10
即13,19均可以被湊出來
而第二組中的5個數都不能將其餘的數湊出來(或被湊出來)
因此直接輸出了5
因此就排序看看能不能湊出來就好啦
a[i]=0表示沒有i這個數,a[i]=1表示能夠湊出i這個數,a[i]=2表示自己就有i這個數
若是處理完成以後a[1~n]中還有等於2的(即自己就有這個數而且不能湊(只能他湊別人))
就讓ans++,最後輸出就行了
說實在的我看懂了,可是我不知道爲啥我打不出來,慘
附上dalao的代碼
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #include<queue> #include<stack> #include<deque> #define INF 0x3f3f3f3f using namespace std; int a[25001]; int b[101]; int t,n,ans=0; inline int read() { char c=getchar(); int x=0,f=1; while(c<'0'||c>'9') {if(c=='-')f=-1;c=getchar();} while(c>='0'&&c<='9')x=x*10+c-48,c=getchar(); return x*f; } int main() { //freopen("money.in","r",stdin); //freopen("money.out","w",stdout); t=read(); while (t--) { ans=0; memset(a,0,sizeof(a)); scanf("%d",&n); for (int i=1; i<=n; i++) { b[i]=read(); a[b[i]]=2;//自己就有b[i]這個數; } sort(b+1,b+1+n);//從小到大排序 for (int i=1; i<=b[n]; i++) { if(a[i]>0) {//若是能夠湊出i //那麼也能夠湊出i+b[j] for(int j=1; j<=n; j++) { if(i+b[j]<=b[n])//排序以後,b[n]必定是b數組中最大的數,在這裏防止越界 a[i+b[j]]=1; else break;//越界的話直接退出 } } } for(int i=1; i<=b[n]; i++) if(a[i]==2) ans++;//統計a[i]==2的個數輸出 printf("%d\n",ans); } }
我太LJ了,因此代碼仍是看dalao的比較實在。
在有向圖 G 中,每條邊的長度均爲1,現給定起點和終點,請你在圖中找一條從起點到終點的路徑,該路徑知足如下條件:
路徑上的全部點的出邊所指向的點都直接或間接與終點連通。
在知足條件1的狀況下使路徑最短。
注意:圖 G 中可能存在重邊和自環,題目保證終點沒有出邊。
請你輸出符合條件的路徑的長度。
第一行有兩個用一個空格隔開的整數 n 和 m,表示圖有 n 個點和 m 條邊。
接下來的 m 行每行 2 個整數 x,y之間用一個空格隔開,表示有一條邊從點 x 指向點y。
最後一行有兩個用一個空格隔開的整數 s, t表示起點爲 s,終點爲 t。
輸出只有一行,包含一個整數,表示知足題目描述的最短路徑的長度。若是這樣的路徑不存在,輸出−1。
3 2
1 2
2 1
1 3
-1
6 6
1 2
1 3
2 6
2 5
4 5
3 4
1 5
3
如上圖所示,箭頭表示有向道路,圓點表示城市。起點1與終點3不連通,因此知足題目描述的路徑不存在,故輸出−1 。
如上圖所示,知足條件的路徑爲1->3->4->5。注意點2不能在答案路徑中,由於點2連了一條邊到點6,而點6 不與終點5 連通。
對於30%的數據,0 < n ≤ 10,0 < m ≤ 20;
對於60%的數據,0 < n ≤ 100,0 < m ≤ 2000;
對於100%的數據,0 < n ≤ 10000 ,0 < m ≤ 200000,0 < x , y , s , t ≤ n,x,s ≠ t。
我不會這道題!!!
我不會這道!!!
我不會這!!!
我不會!!!
我不!!!
我!!!
!!!
!!
!
#include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> #include<iomanip> #include<stack> #include<queue> #include<map> #include<list> #include<set> #include<cctype> #include<bitset> #define N 20000 #define M 400000 #define Q 300000 #define INF 0x7fffffff using namespace std; struct edge { int u,v,next; //int num; } a[M]; int head[N]; bool vis[N]; int num=0; int n,m; int s,t; bool lala[N],mama[N]; int opt[N],uxv[N]; void add_edge(int x,int y) { a[++num].u=x; a[num].v=y; a[num].next=head[x]; head[x]=num; } inline int read() { int num=0,f=1; char c=getchar(); for(; !isdigit(c); c=getchar()) if(c=='-') f=-1; for(; isdigit(c); c=getchar()) num=num*10+c-'0'; return num*f; } int SPFA(int x,int y) { int headd=-1,tail=0; for(int i=1; i<=n; i++) opt[i]=INF; opt[x]=0; uxv[0]=x; vis[x]=mama[x]=true; while(headd!=tail) { headd=(headd+1)%M; int uu=uxv[headd]; int vv; for(int i=head[uu]; i; i=a[i].next) if(opt[uu]+1<opt[vv=a[i].v]) { opt[vv]=opt[uu]+1; if(!vis[vv]) { tail=(tail+1)%M; uxv[tail]=vv; vis[vv]=true; mama[vv]=true; } } vis[uu]=false; } if(opt[y]==INF) return -1; return opt[y]; } int main() { /*freopen("road.in","r",stdin); freopen("road.out","w",stdout);*/ n=read(); m=read(); for(int i=1; i<=m; i++) { int x,y; x=read(); y=read(); add_edge(y,x); } s=read(); t=read(); SPFA(t,n+1); for(int i=1; i<=n; i++) lala[i]=mama[i]; for(int i=1; i<=m; i++) if(mama[a[i].u]==false) lala[a[i].v]=false; memset(head,0,sizeof(head)); memset(vis,false,sizeof(vis)); num=0; for(int i=1; i<=m; i++) if(lala[a[i].u] && lala[a[i].v]) add_edge(a[i].v,a[i].u); printf("%d\n",SPFA(s,t)); return 0; }
綜上所述:我就是個弟弟。