题意:
给出一个数字k,要求你构造一张无向图使得点1到点2的最短路径恰好有k条
首先将k二进制化,然后看图就明白怎么构造了:
拿k=7来说
首先构造出最大的2的指数级部分,然后接下来在此链上继续并联一些点
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<iostream>
#include<map>
using namespace std;
map<int,int>mp;
int pw[30];
char g[2005][2005];
int n;
int len;
int cnt;
void F(int k)
{
++cnt;
g[1][cnt]=g[cnt][1]='Y';
mp[0]=3;
for(int i=1; i<=k; i++)
{
g[cnt+1][cnt]=g[cnt][cnt+1]='Y';
g[cnt+2][cnt]=g[cnt][cnt+2]='Y';
g[cnt+3][cnt+1]=g[cnt+1][cnt+3]='Y';
g[cnt+3][cnt+2]=g[cnt+2][cnt+3]='Y';
cnt+=3;
mp[i]=cnt;
}
g[cnt][2]=g[2][cnt]='Y';
}
void F2(int k)
{
int st=mp[k];
k<<=1;
while(k<len*2)
{
g[cnt+1][st]=g[st][cnt+1]='Y';
st=++cnt;
k++;
}
g[st][2]=g[2][st]='Y';
}
int main()
{
pw[0]=1;
for(int i=1; i<=30; i++) pw[i]=pw[i-1]*2;
memset(g,'N',sizeof g);
scanf("%d",&n);
cnt=2;
for(int i=30; i>=0; i--)
{
if(n>=pw[i])
{
len=i;
F(i);
n-=pw[i];
break;
}
}
for(int i=30; i>=0; i--)
{
if(n>=pw[i])
{
F2(i);
n-=pw[i];
}
}
printf("%d\n",cnt);
for(int i=1; i<=cnt; i++)
{
for(int j=1; j<=cnt; j++)
{
printf("%c",g[i][j]);
}
puts("");
}
return 0;
}