解析
关键性质:三元环合法等价于边权和模3等于0。
还有一个常识:三元环的级别是O(mm)O(m\sqrt m)O(mm)。
证明:
三个点度数都大于 m\sqrt mm 的点不超过Cm3=mmC_{\sqrt m}^3=m\sqrt mCm3=mm 个。
如果含有度数小于m\sqrt mm 的点,考虑从这样的点伸出去的每条边,最多和 m\sqrt mm 条边配对成环,所以也不超过 mmm\sqrt mmm 个。
所以本题暴力找出所有的三元环高斯消元就行了,常数很小。
看题解学会了一直因为惯性懒得学的高斯约旦法。
暴力高消确实挺不容易想到的,总会往神仙构造那边想。
但第一个关键性质没有看出来不太应该。
代码
//luogu
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define ull unsigned long long
#define debug(...) fprintf(stderr,__VA_ARGS__)
#define ok debug("OK\n")
using namespace std;const int N=2e5+100;
const int inf=1e9;
const int mod=998244353;
inline ll read(){ll x(0),f(1);char c=getchar();while(!isdigit(c)) {if(c=='-')f=-1;c=getchar();}while(isdigit(c)) {x=(x<<1)+(x<<3)+c-'0';c=getchar();}return x*f;
}int n,m;
int id[80][80];
int a[5050][270],num;
int ans[270];
void print(int n,int m){for(int i=1;i<=n;i++){for(int j=1;j<=m;j++) printf("%d ",a[i][j]);puts("");}puts("");
}signed main(){#ifndef ONLINE_JUDGEfreopen("a.in","r",stdin);freopen("a.out","w",stdout);#endifint T=read();while(T--){num=0;memset(id,0,sizeof(id));memset(a,0,sizeof(a));memset(ans,0,sizeof(ans));n=read();m=read();for(int i=1;i<=m;i++){int x=read(),y=read(),w=read();id[x][y]=id[y][x]=i;if(w!=-1){++num;a[num][i]=1;a[num][m+1]=w;} }for(int x=1;x<=n;x++){for(int y=x+1;y<=n;y++){for(int z=y+1;z<=n;z++){if(id[x][y]&&id[y][z]&&id[x][z]){++num;a[num][id[x][y]]=a[num][id[x][z]]=a[num][id[y][z]]=1;a[num][m+1]=0;}}}}//printf("num=%d\n",num);int id=0;//print(num,m+1);for(int i=1;i<=m;i++){int pos=0;for(int j=id+1;j<=num;j++){if(a[j][i]){pos=j;break;}}if(!pos) continue;++id;swap(a[id],a[pos]);if(a[id][i]==2){for(int j=i;j<=m+1;j++) a[id][j]=(3-a[id][j])%3;}for(int j=1;j<=num;j++){if(j!=id&&a[j][i]){//printf("j=%d\n",j);int x=a[j][i];for(int k=i;k<=m+1;k++){a[j][k]=(a[j][k]-x*a[id][k]+6)%3;//printf(" k=%d %d*%d\n",k,a[j][i],a[id][k]);}}}//print(num,m+1);}bool flag=0;for(int i=id+1;i<=num;i++){if(a[i][m+1]){puts("-1");flag=1;break;}}if(flag) continue;for(int i=1;i<=id;i++){for(int p=1;p<=m;p++){if(a[i][p]){ans[p]=a[i][m+1];break;}}}for(int i=1;i<=m;i++) printf("%d ",ans[i]?ans[i]:3);puts("");}return 0;
}
/*
*/