题意:
分析
如果可以使得二分图的某一侧全为0,另一侧全不为0,那么一定可以满足条件。
显然,左侧点权之和=右侧点权之和(mod 3)
因此,不为0的一侧就必须满足点权和mod 3=0
这个限制是非常弱的:如果这一侧总点数为 3 ∗ k 3*k 3∗k,那么直接所有都为1即可。
如果为 3 ∗ k + 1 3*k+1 3∗k+1,那么拿两个数来换成2.
如果为 3 ∗ k + 2 3*k+2 3∗k+2,那么拿一个数来换成2.
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define SF scanf
#define PF printf
#define MAXN 100010
using namespace std;
int n1,n2,m;
int ans[MAXN];
vector<pair<int,int> >a[MAXN];
vector<int> p1[MAXN],p2[MAXN];
int col[MAXN];
int fa[MAXN];
int get_fa(int x){
if(fa[x]==0)
return x;
fa[x]=get_fa(fa[x]);
return fa[x];
}
void dfs(int x,int fax,int id){
for(int i=0;i<int(a[x].size());i++){
int u=a[x][i].first;
if(u==fax)
continue;
dfs(u,x,a[x][i].second);
col[x]-=col[u];
}
ans[id]=(col[x]%3+3)%3;
}
int main(){
SF("%d%d%d",&n1,&n2,&m);
int u,v;
for(int i=1;i<=m;i++){
SF("%d%d",&u,&v);
v+=n1;
int u1=get_fa(u),v1=get_fa(v);
if(u1!=v1){
a[u].push_back(make_pair(v,i));
a[v].push_back(make_pair(u,i));
fa[u1]=v1;
}
}
for(int i=1;i<=n1;i++)
p1[get_fa(i)].push_back(i);
for(int i=n1+1;i<=n1+n2;i++)
p2[get_fa(i)].push_back(i);
for(int i=1;i<=n1+n2;i++)
if(fa[i]==0){
if(p1[i].size()==1&&p2[i].size()==1){
PF("-1");
return 0;
}
if(p1[i].size()==1)
swap(p1[i],p2[i]);
for(int j=0;j<int(p1[i].size());j++)
col[p1[i][j]]=1;
if(p1[i].size()%3)
col[p1[i][0]]++;
if(p1[i].size()%3==1)
col[p1[i][1]]++;
dfs(i,0,0);
}
for(int i=1;i<=m;i++)
PF("%d ",ans[i]);
}