CF350E Wrong Floyd

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\n",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\n",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\n",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 } 

 

posted @ 2018-09-20 21:08  degage  阅读(189)  评论(0编辑  收藏  举报