题意:一个无向图,每条边有黑白两种颜色,要求用最少的反色刷使得所有边变为白色,注意刷子会回到出发点。
明显欧拉回路,注意到欧拉回路的性质,即无向图任意点的点数不能使奇数。那么我们用并查集维护每个连通块内黑色边的数量以及他们的度数,用桶存起来。一个基本的维护。
既然涉及到了,就顺便贴一波相关吧。
判断欧拉路是否存在的方法
有向图:图连通,有一个顶点出度大入度1,有一个顶点入度大出度1,其余都是出度等于入度。
无向图:图连通,只有两个顶点是奇数度,其余都是偶数度的。
判断欧拉回路是否存在的方法
有向图:图连通,所有的顶点出度等于入度。
无向图:图连通,所有顶点都是偶数度。
#include<cstdio>
#include<algorithm>
#include<cstring>
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define fd(i,a,b) for(int i=a;i>=b;i--)
using namespace std;
const int N=1e6+5;
int n,m,cnt[3],d[N];
int f[N],size[N],ans;
struct node
{
int x,y,z;
}e[N];
inline int find(int x)
{
if (f[x]==x)return x;
else return f[x]=find(f[x]);
}
int main()
{
scanf("%d%d",&n,&m);
fo(i,1,n)f[i]=i;
fo(i,1,m)
{
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
e[i].x=x,e[i].y=y,e[i].z=z;
if (!z)d[x]+=2,d[y]+=2;
else d[x]++,d[y]++;
int fx=find(x),fy=find(y);
if (fx!=fy)f[fx]=fy;
}
fo(i,1,n)++cnt[d[i]%2];;
fo(i,1,m)
{
int x=e[i].x,y=e[i].y,z=e[i].z;
int fx=find(x);
if (z)
{
if (!size[fx])++ans;
++size[fx];
}
}
int q;
scanf("%d",&q);
while (q--)
{
int op;
scanf("%d",&op);
if(op==1)
{
int id;
scanf("%d",&id);
int x=e[++id].x,y=e[id].y,z=e[id].z;
int fx=find(x);
if(!z)
{
if (!size[fx])ans++;
size[fx]++;
cnt[d[x]%2]--,cnt[d[y]%2]--;
d[x]--,d[y]--;
cnt[d[x]%2]++,cnt[d[y]%2]++;
}
else
{
--size[fx];
if (!size[fx])ans--;
cnt[d[x]%2]--,cnt[d[y]%2]--;
d[x]++,d[y]++;
cnt[d[x]%2]++,cnt[d[y]%2]++;
}
e[id].z=1-z;
}
else
{
int tmp=ans;
if (cnt[1])tmp=-1;
printf("%d\n",tmp);
}
}
}