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; }
综上所述:我就是个弟弟。