codeforces 388B Fox and Minimal path

      给一个数k,让构造出一个节点数小于1000的图,使得这个图上从1到2的最短路的路径数恰好为k.

      当天做的时候直接想到分解质因数去做,但这么做对大质数无解=然后就被cha掉了...今天在网上看到一个神奇的做法...

原帖在这:http://7-sun.com/text/25918.html


举个例子

1

3 4 5

6 7 8

9 10 11

2

除了起点终点,每一层三个节点,3和6,7连边,4和6,7连边,然后6和9,10连边,7和9,10连边,然后5--8--11连边得到初始的图。然后1--5,11--2连接,把k分解成二进制表示形式,这样从上到下每一层分别对应k从高位到低位的每一位,比如若最高位为1,那么5和6,7连边,否则不变。然后检测每一位的01状态,到最低位的时候,若最低位为1,就把9--2,,10--2也连上,这样就是最终的结果了。这么做,最多只会用到不到100个点...

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
using namespace std;
typedef long long ll;
bool g[200][200];
int bi[100];
int ct;
int n,m,p,q,k;
void init()
{
    int x=3,y=4,z=5;
    int nx=6,ny=7,nz=8;
    for (int i=1; i<=30; i++)
    {
        g[x][nx]=g[x][ny]=true;
        g[y][nx]=g[y][ny]=true;
        g[z][nz]=true;
        x=nx; y=ny; z=nz;
        nx+=3;ny+=3; nz+=3;
    }
    g[1][5]=true;
}
int main()
{
    init();
    cin>>k;
    ct=0;
    while (k)
    {
       bi[ct++]=(k&1);
       k>>=1;
    }
    int j=0;
    for (int i=ct-1; i>0; i--,j+=3)
    {
        if (bi[i])
        {
            g[5+j][5+j+1]=true;
            g[5+j][5+j+2]=true;
        }
    }
    j-=3;
    g[5+j+1][2]=true;
    g[5+j+2][2]=true;
    if (bi[0]) g[5+j+3][2]=true;
    int nn=5+j+3;
    cout<<nn<<endl;
    for (int i=1; i<=nn; i++)
     {
        for (int j=1; j<=nn; j++)
         if (g[i][j] || g[j][i]) cout<<"Y";
         else cout<<"N";
        cout<<endl;
     }
    return 0;
}


你可能感兴趣的:(codeforces 388B Fox and Minimal path)