http://acm.hdu.edu.cn/showproblem.php?pid=4781
先构造一个权值模3为0的大圈 平方预处理一下所有弧(共n*(n-1)/2条弧) 然后用剩下的边来和圈上的某个弧来凑成权值模3为0的小圈 这样不会破坏已经构造好的圈 并且一次只消耗一条弧
#include <bits/stdc++.h>
using namespace std;
#define pii pair <int,int>
struct node
{
int u;
int v;
int w;
};
pii v[3][10000];
node edge[10010];
int e[100][100];
int dis[100][100];
int sz[3];
int n,m;
void init()
{
int i,j,k;
memset(dis,0,sizeof(dis));
for(i=0;i<n;i++)
{
for(j=0,k=i;j<n-1;j++,k=(k+1)%n)
{
dis[i][edge[k].v]=dis[i][edge[k].u]+edge[k].w;
}
}
sz[0]=0,sz[1]=0,sz[2]=0;
for(i=0;i<n;i++)
{
for(j=0,k=(i+2)%n;j<n-3;j++,k=(k+1)%n)
{
if(dis[i][k]%3==0) v[0][sz[0]++]=make_pair(k,i);
else if(dis[i][k]%3==1) v[2][sz[2]++]=make_pair(k,i);
else v[1][sz[1]++]=make_pair(k,i);
}
}
}
int main()
{
pii tmp;
int t,cas,i,flag;
scanf("%d",&t);
for(cas=1;cas<=t;cas++)
{
scanf("%d%d",&n,&m);
memset(e,0,sizeof(e));
for(i=0;i<m;i++) edge[i].w=i+1;
if(n%3==1) swap(edge[n-1].w,edge[n+1].w);
for(i=0;i<n;i++)
{
e[i][(i+1)%n]=1;
e[(i+1)%n][i]=1;
edge[i].u=i,edge[i].v=(i+1)%n;
}
init();
flag=1;
for(i=n;i<m;i++)
{
if(sz[edge[i].w%3]>0)
{
flag=0;
while(sz[edge[i].w%3]>0)
{
sz[edge[i].w%3]--;
tmp=v[edge[i].w%3][sz[edge[i].w%3]];
if(e[tmp.first][tmp.second]==0)
{
e[tmp.first][tmp.second]=1;
e[tmp.second][tmp.first]=1;
edge[i].u=tmp.first,edge[i].v=tmp.second;
flag=1;
break;
}
}
}
else
{
flag=0;
break;
}
}
printf("Case #%d:\n",cas);
if(flag) for(i=0;i<m;i++) printf("%d %d %d\n",edge[i].u+1,edge[i].v+1,edge[i].w);
else printf("-1\n");
}
return 0;
}