hdu4781 Assignment For Princess(构造)

时间:2023-03-09 03:46:37
hdu4781 Assignment For Princess(构造)

题目链接:hdu4781 Assignment For Princess

题意:n个点m条边,每条有向边的权值分别是1,2,3…m,一个点能到达任意一个点,没有重边和自环,没有任何两条边的权值相同,任意一个有向环的权值和必须是3的倍数,现在需要把这个图输出来。

题解:注意到题目给出的范围m >= n+3,所以一定是可以构造出一个1~n的回路使得权值和为3的倍数的,可以让前n-1条边权值为1~n-1,第n条边(n->1)可以为n, n+1, n+2从而满足题意,后面再连任意两条不相邻的边时,边权模3的大小和原来构造出的第一条回路中两条边的距离大小相等即可。

第一遍自己做没构造成功(失败的代码太丑就不贴了orz),后来参考了这个博客:http://blog.****.net/cevaac/article/details/41007703

感觉这类题挺有趣的,我还差得远,加油呐!

 #include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#define CLR(a,b) memset((a),(b),sizeof((a)))
using namespace std; const int inf = 0x3f3f3f3f;
const int mod = 1e9 + ;
const int N = ;
const int M = ;
int n, m;
int g[M][];
int cnt[];//边权值模3为0,1,2的个数
int d[M];//顶点i到1的距离(1~n构造第一个回路)
int main(){
int t, i, j, k, x, p;
scanf("%d", &t);
for(k = ; k <= t; ++k){
printf("Case #%d:\n", k);
CLR(d, );
CLR(cnt, );
scanf("%d%d", &n, &m);
for(i = ; i <= n-; ++i){//前n-1条边权为1...n-1
printf("%d %d %d\n", i, i+, i);
d[i+] = d[i] + i;
}
for(i = n; i <= m; ++i){
x = i % ;
cnt[x]++;
g[cnt[x]][x] = i;
}
p = ( - d[n]%) %;//满足构造出的第一个回路权值和为3的倍数
printf("%d 1 %d\n", n, g[cnt[p]--][p]);
for(i = ; i <= n-; ++i){
for(j = i+; j <= n; ++j){
if(i == && j == n)
continue;
p = (d[j] - d[i]) % ;
if(cnt[p])
printf("%d %d %d\n", i, j, g[cnt[p]--][p]);
}
}
}
return ;
}