Jamie and Interesting Graph CodeForces #916C[题解]

题目来源


http://codeforces.com/contest/916/problem/C

题意理解


Jamie has recently found undirected weighted graphs with the following properties very interesting:

The graph is connected and contains exactly n vertices and m edges.
All edge weights are integers and are in range [1, 109] inclusive.
The length of shortest path from 1 to n is a prime number.
The sum of edges’ weights in the minimum spanning tree (MST) of the graph is a prime number.
The graph contains no loops or multi-edges.
If you are not familiar with some terms from the statement you can find definitions of them in notes section.

Help Jamie construct any graph with given number of vertices and edges that is interesting!

Input
First line of input contains 2 integers n, m ( 2 n 10 5   , n 1 m m i n ( 10 5 , n ( n 1 ) 2 ) ) — the required number of vertices and edges.

Output
In the first line output 2 integers sp, mstw ( 1 s p , m s t w 10 14 ) ) — the length of the shortest path and the sum of edges’ weights in the minimum spanning tree.

In the next m lines output the edges of the graph. In each line output 3 integers u , v , w ( 1 u , v n , 1 w 10 9 ) describing the edge connecting u and v and having weight w.

Sample

input

4 4

output

7 7
1 2 3
2 3 2
3 4 2
2 4 4

给出 n 个点, m 个点. 要求组成一个最小生成树权重之和及始点到终点的最短路权重之和都为质数的图. 输出为最短路权重之和, 最小生成树权重之和一行, 两个点和连接它们的边的权一行.

解题思路


必须要承认, 这道题一眼望去似乎难如登天, 毕竟要硬生生构造一个图. 冥思苦想不能解, 谷歌一搜竟无言.

扫描二维码关注公众号,回复: 1947729 查看本文章

我们可以直接构造一条路径P, 路径上包括了所有 n 个结点. 我们接下来找到大于 n 的某个质数, 直接令这条路径作为生成树和最短路, 其权重之和等于这个质数. 这点相当容易办到: 前n-2条边设为1, 最后一条设为 质数-n+2.

那么, 剩下的m-n+1条边, 我们只需要随便找几个点, 统一分配1000000这样超大的权即可.

需要注意的是, 要寻找到比 n 更大的素数, 我们只需在 [ n , 2 n ] 这个区间寻找即可. 这是由Bertrand’s postulate所说明的, 它指出若 n 2 , 则在此区间内必然有素数存在. 相关的证明可以在Ramanujan, S. (1919), “A proof of Bertrand’s postulate”, Journal of the Indian Mathematical Society, 11: 181–182找到.

代码实现


#include <iostream>
#include <vector>
#include <math.h>
#include <time.h>
using namespace std;

int findPrimes(int n)
{
    int ceil = 2 * n;
    vector<int> is_primes(ceil + 1, 1);
    is_primes[1] = 0;
    int threshold=int(sqrt(ceil))+1;
    for (int j = 2; j < threshold; j++) if (is_primes[j]) for (int k = j*j; k <= ceil; k += j)  is_primes[k] = 0;
    for (int ret = n; ret <= ceil; ret++) if (is_primes[ret]) return ret;
}

int main()
{
    int n, m;
    scanf("%d%d", &n, &m);
    int prime = findPrimes(n);
    printf("%d %d\n1 2 %d\n", prime,prime,prime - n + 2);
    for (int i = 0; i < n - 2; i++) printf("%d %d 1\n", i + 2, i + 3);
    m = m - n + 1;
    for (int i = 0; i < n; i++) {
        for (int j = i+2; j < n; j++) {
            if (m-- == 0)   return 0;
            printf("%d %d 1000000000\n", i + 1, j + 1);         
        }
    }
}

代码表现


916-c

猜你喜欢

转载自blog.csdn.net/wayne_mai/article/details/80541967
今日推荐