题目链接:这里
题意:构造一个n个点,m条有向边的图,需要满足两个要求:
1.任意一对点对之间最多有一条有向边,且没有自环。
2.保证图联通,m条边的边权严格属于[1, m]且互不相同,从任意点出发,经过任意路径后回到起始点,经过的边权总和是3的倍数。
解法:构造好题,方法 对于每个点i < n构造出i~i+1权值为i的边,用n~1调整权值构造出环,然后其余权值为w的边在i~j且i~j权值与w对3同余的路径上添加。

//HDU 4781

#include <bits/stdc++.h>
using namespace std;
const int maxn = 6500;
int cnt[4]; //记录模3系权值的出现次数
int f[maxn][4]; //f[i][j],权值为j,的边有哪些
int sum[maxn];
int main()
{
    int T, ks = 0, n, m;
    scanf("%d", &T);
    while(T--){
        scanf("%d%d", &n, &m);
        printf("Case #%d:\n", ++ks);
        memset(cnt, 0, sizeof(cnt));
        memset(f, 0, sizeof(f));
        //先n个点构成1个环
        for(int i = 1; i < n; i++){
            printf("%d %d %d\n", i, i + 1, i);
            sum[i + 1] = sum[i] + i;
        }
        for(int i = n; i <= m; i++){
            int x = i%3;
            f[++cnt[x]][x] = i;
        }
        int lastedge = (3 - (sum[n] - sum[1]) % 3) % 3;
        printf("%d 1 %d\n", n, f[cnt[lastedge]--][lastedge]);
        //构造剩下的n - m条边
        for(int i = 1; i <= n - 2; i++){
            for(int j = i + 2; j <= n; j++){
                if(i == 1 && j == n) continue;
                int curedge = (sum[j] - sum[i] + 3) % 3;
                if(cnt[curedge]){
                    printf("%d %d %d\n", i, j, f[cnt[curedge]--][curedge]);
                }
            }
        }
    }
    return 0;
}