Description
给定n个点,m条边以及k个标记点,要求进行Floyd时只以标记的点为中间点进行松弛操作(每条边边权为1)要求你造出m条边的数据来hack掉这种程序。
Hint
3<=n<=300 , 2<=k<=n2<=k<=n , n-1<=m<=n*(n-1)/2;
Solution
我们只需要任意一点只和非标记点连边就可以了(这样就无法正确更新它到其他点的距离)
具体一下几个细节:
1.判k==n或m>最多可以构出的边maxm;
maxm=(n-1)*(n-2)/2+num;(num:非标记点的数量)
2.将随便一个标记点与所以非标记点连边;
3.再随便一个非标记点与未加入图中的点连边来保证图的联通;
4.最后随便加未加的边使边数凑够m即可;
Code
1 #include<bits/stdc++.h> 2 #define maxn 310 3 using namespace std; 4 int n,m,k,x,num; 5 bool vis[maxn],iss[maxn][maxn],viss[maxn]; 6 void init(){ 7 scanf("%d%d%d",&n,&m,&k); 8 for(int i=1;i<=n;i++) iss[i][i]=1; 9 for(int i=1;i<=k;i++) scanf("%d",&x),vis[x]=1; 10 num=n-k; 11 int maxx=(n-1)*(n-2)/2+num; 12 if(m>maxx||k==n){ 13 printf("-1");return; 14 } 15 int t,tt=1;int calc=0; 16 while(!vis[tt]) tt++; 17 viss[tt]=1; 18 for(int i=1;i<=n;i++){ 19 if(!vis[i]){ 20 t=i; 21 viss[t]=1; 22 printf("%d %d ",t,tt); 23 iss[t][tt]=iss[tt][t]=1; 24 calc++; 25 } 26 } 27 28 //保证联通 29 for(int i=1;i<=n;i++){ 30 if(viss[i]) continue; 31 printf("%d %d ",i,t); 32 iss[i][t]=iss[t][i]=1; 33 calc++; 34 if(calc==m) break; 35 } 36 37 38 for(int i=1;i<=n;i++){ 39 if(calc==m) break; 40 if(i==tt) continue; 41 for(int j=1;j<=n;j++){ 42 if(j==tt) continue; 43 if(iss[i][j]) continue; 44 printf("%d %d ",i,j); 45 calc++; 46 iss[i][j]=iss[j][i]=1; 47 if(calc==m) break; 48 } 49 } 50 } 51 int main(){ 52 init(); 53 54 return 0; 55 }