做了4天ICM 感觉脑子都坏掉了… CF落下了2场的题 赶紧追 >.<
题意:
最多用1000个点 画出一幅图 要求满足1节点到2节点的最短路条数为k 输出这幅图的邻接矩阵
思路:
一看k的值10^9 果断开始构造最短路的走法 直觉告诉我们要采用类似BFS的方式(一层一层的加点 这样满足构造出的路径等长)
我首先想的是利用素数去构造 因为素数能构造出合数 可是如果要求最短路条数是一个很大的素数就不好搞(这个思路应该可以继续 我嫌麻烦换了思路 现在想想就是如果遇到大素数情况就异或1 变成最接近的合数递归的做)
由于k最多10位数字 所以我们可以按数字位构造 例如:
k=321 那么我们可以令最短路长度为3 百位、十位、个位分别构造成 3*10*10、2*10*1、1*1*1
构造方法有了 下面要验证下点够不够用 最费点的就是999999999 但它只需要500-个点 题目给的点太多了
这题要是改成使用的点的个数尽量少就难做了(上面的递归想法可能可以解决) 不过并无此要求
代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;
int aim,top;
int bit[11];
vector<int> floor[11];
char maz[1001][1001];
int main()
{
int i,j,node=3,k,f,s0,s1;
memset(maz,'N',sizeof(maz));
scanf("%d",&aim);
while(aim)
{
bit[++top]=aim%10;
aim/=10;
}
for(i=1;i<=top;i++)
{
for(j=1;j<=top;j++) floor[j].clear();
for(j=1;j<i;j++)
{
for(k=10;k;k--)
{
floor[j].push_back(node);
node++;
}
}
for(j=1;j<=bit[i];j++)
{
floor[i].push_back(node);
node++;
}
for(j=i+1;j<=top;j++)
{
floor[j].push_back(node);
node++;
}
for(k=floor[1].size(),j=0;j<k;j++) maz[1][floor[1][j]]=maz[floor[1][j]][1]='Y';
for(k=floor[top].size(),j=0;j<k;j++) maz[2][floor[top][j]]=maz[floor[top][j]][2]='Y';
for(f=2;f<=top;f++)
{
for(s0=floor[f-1].size(),j=0;j<s0;j++)
{
for(s1=floor[f].size(),k=0;k<s1;k++)
maz[floor[f-1][j]][floor[f][k]]=maz[floor[f][k]][floor[f-1][j]]='Y';
}
}
}
printf("%d\n",node-1);
for(i=1;i<node;i++)
{
for(j=1;j<node;j++) printf("%c",maz[i][j]);
printf("\n");
}
return 0;
}