bzoj3706反色刷 尤拉圖+並查集(尤拉圖性質簡介)
阿新 • • 發佈:2019-02-05
題意:一個無向圖,每條邊有黑白兩種顏色,要求用最少的反色刷使得所有邊變為白色,注意刷子會回到出發點。
明顯歐拉回路,注意到歐拉回路的性質,即無向圖任意點的點數不能使奇數。那麼我們用並查集維護每個連通塊內黑色邊的數量以及他們的度數,用桶存起來。一個基本的維護。
既然涉及到了,就順便貼一波相關吧。
判斷尤拉路是否存在的方法
有向圖:圖連通,有一個頂點出度大入度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);
}
}
}