【链接】:
【题意】:给定一棵树,要求拆成若干条简单路径,并且这些路径都经过一个公共节点。给出任意一个解决方案,如不存在输出No。 【分析】:因为是一棵树, 所以如果要求任意两条路线至少有一个公共点, 到最后, 所有的路线都会有唯一的公共点. 如果有两个公共点的话, 就至少有两条路线只包含其中的一条路线, 否则就会有环, 有了环就不是树了.也就是说, 所有的点, 除了那个唯一的公共点, 必须度数小于 2 .在所有点之中:度数为 1 的点是路线的一个端点.度数为 2 的是一条路线中除了两端以外的点.度数大于 2 的是路线的公共点. 如果有两个及以上的点的度数是大于 2 的, 代表不可能路线中任意两条至少交于一点, 输出 No.如果没有度数大于 2 的点, 代表只有一条路线.如何输出路线:先输出 Yes, 代表可以将树分解.接着输出路线的个数, 也就是度数为 1 的点的个数.接着, 对于每条路线, 输出其中一个度数为 1 的点和 唯一的 公共点.注意: 如果没有度数大于 2 的点, 代表只有一条路线, 此时路线个数并不等于度数为 1 的点的个数, 并且端点就是两个度数为 1 的点.
【代码】:
#includeusing namespace std;int n;int deg[100005]; // 每个点的度数int leaves[100005], comv[100005]; // leaves 存储度数为 1 的端点, comv 存储公共点int nleaf = 0, ncomv = 0; // 存储度数为 1 的点与公共点的数量int x,y;/*有三种可能情况:所有链在某一点上相交,也就是只有一个点度数>2;只有一条链,就是两个点度数为1,其他点度数为2;不符合要求的情况,就是有超过一个点度数>2*/int main(){ int n; scanf("%d",&n); for(int i=1;i 2) comv[++ncomv]=i; } //如果公共点不唯一, 就输出 "No" if(ncomv>1) {printf("No\n");return 0;}//不符合要求的情况,就是有超过一个点度数>2 printf("Yes\n"); // 如果只有一条路线, 就输出两端 (即两个度数为 1 的点) if(ncomv==0) printf("1\n%d %d\n",leaves[1],leaves[2]);//只有一条链,就是两个点度数为1,其他点度数为2; else//所有链在某一点上相交,也就是只有一个点度数>2; { printf("%d\n",nleaf);//度数为1的点的个数 for(int i=1;i<=nleaf;i++) { printf("%d %d\n",comv[1],leaves[i]);//公共点与一个度数为1的点 } } return 0;}