C240518A. 传送门(portal)
构造一个图使得点\(1\)到\(2\)的最短路正好有\(k\)条,使构造出的图点的个数\(N\le n_5\)
考虑\(k=2^t\)那么可以轻松构造出如下的图
对于其他的情况可以考虑二进制拆分,如\(k=10\)时为了,使最短路长度固定加入点\(9\)
对\(k=10^9\),只需构造\(80\)个点,可以通过
(考场时一直以为是要构造的图的边数小于\(165\),想了差不多一个小时
代码:
#include<cstdio>
int k,n1,n2,n3,n4,n5;
int N,M,top,a[50],low;
struct Edge{int u,v;Edge(){}Edge(int x,int y){u=x,v=y;}
}edge[1005];
int main(){scanf("%d%d%d%d%d%d",&k,&n5,&n4,&n3,&n2,&n1);if(k==1)printf("2 1\n1 2");else if(k==2)printf("4 4\n1 3\n1 4\n2 3\n2 4");else if(k==3)printf("5 6\n1 3\n1 4\n1 5\n2 3\n2 4\n2 5");else{while(k)a[top]=k&1,top++,k>>=1;for(int i=31;~i;i--)if(a[i]){top=i;break;}for(int i=0;i<32;i++)if(a[i]){low=i;break;}edge[++M]=Edge(1,3);edge[++M]=Edge(1,4);for(int i=2;i<=top;i++){edge[++M]=Edge(i*2-1,i*2+1);edge[++M]=Edge(i*2-1,i*2+2);edge[++M]=Edge(i*2,i*2+1);edge[++M]=Edge(i*2,i*2+2);}N=2*top+2;edge[++M]=Edge(2,N);edge[++M]=Edge(2,N-1);if(top!=low){N++;edge[++M]=Edge(1,N); if(a[top-1]){edge[++M]=Edge(N,5);edge[++M]=Edge(N,6);}if(low==0){for(int i=top-2;i>=1;i--){N++;edge[++M]=Edge(N-1,N);if(a[i]){edge[++M]=Edge(N,(top-i+1)*2+1);edge[++M]=Edge(N,(top-i+1)*2+2);}}N++;edge[++M]=Edge(N-1,N);edge[++M]=Edge(N,2);}else{for(int i=top-2;i>=low;i--){N++;edge[++M]=Edge(N-1,N);if(a[i]){edge[++M]=Edge(N,(top-i+1)*2+1);edge[++M]=Edge(N,(top-i+1)*2+2);}}}}printf("%d %d\n",N,M);for(int i=1;i<=M;i++)printf("%d %d\n",edge[i].u,edge[i].v);}return fflush(stdout),fclose(stdin),fclose(stdout),0;
}