2017.10.22 方格染色 失败总结

详细题解网上有好多。。

一开始想用一个并查集维护  确定关系

一个并查集维护相等关系

但会出现一些无解判不出来(原因未知)

所以就只能写加权并查集,记录每个点和他根节点的相等关系:0相等 1不等

然后原点选0还是1影响方块 1 0

已填的数影响方块 1 0

坐标影响 方块 1 0

统一一下就可以了


注:

1、分清变量!!!

2、分清变量!!!

3、分清变量!!!



AC 代码:

#include<iostream>
#include<cstdio>
using namespace std;
#define P 1000000000
int fu[2000005],g[2000005],ans,n,m,k,i,j,a[2000005],b[2000005],c[2000005];
bool sy[3];
int find(int o)
{
	if(fu[o]==o)return o;
	int t=find(fu[o]);
	g[o]^=g[fu[o]];
	
	return 	fu[o]=t;
}
int calc()
{
	for(i=1;i<=n+m;i++)fu[i]=i,g[i]=0;
	fu[n+1]=1;
	for(i=1;i<=k;i++)	
	{
		int lx=find(a[i]),ly=find(b[i]);
	
		int lin=g[a[i]]^g[b[i]]^c[i];
		//	cout<<endl<<a[i]<<" "<<b[i]-n<<" "<<c[i]<<endl;
		if(lx!=ly)
		fu[lx]=ly,g[lx]=lin;		
		else 
		{
			if(lin)return 0;
		}
	}
	int daan=-1;
	for(i=1;i<=n+m;i++)
	{
		if(i==find(i))
		if(daan==-1)daan=1;
		else{
			daan*=2;
			if(daan>=P)daan-=P;			
		}
	}
	return daan;
}
int main()
{
	scanf("%d%d%d",&n,&m,&k);
	sy[0]=sy[1]=1;
	for(i=1;i<=k;i++)
	{
		scanf("%d%d%d",&a[i],&b[i],&c[i]);
		if(a[i]==1&&b[i]==1){sy[c[i]]=0,i--,k--;continue;}
		 if((a[i]&1)==0&&(b[i]&1)==0)c[i]^=1;
		b[i]+=n;
	}
	if(sy[1])ans=calc();
	//cout<<ans<<" ";
	if(sy[0])
	{
		for(i=1;i<=k;i++)
		{
	if (a[i]>1 && b[i]>n+1)		c[i]^=1;
		}
		ans+=calc();	
	}
	printf("%d",ans%P);
}






90分莫名wa代码:

#include<iostream>
#include<cstdio>
using namespace std;
#define P 1000000000
#define ll long long
int n,m,i,fu[2000006],fu2[2000006],cnt,a[2000006],b[2000006],c[2000006],k,j,bt[2000006];
bool cx[2000006];
ll ans;
ll ksm(ll a,ll b)
{
    ll ans=1;
    while(b)
    {
        if(b%2)ans=(ans*a)%P;
        b/=2;
        a=(a*a)%P;        
    }    
    return ans;
}
int find(int o)
{
    if(fu[o]!=o)fu[o]=find(fu[o]);
    return fu[o];    
}
int find2(int o)
{
    if(fu2[o]!=o)fu2[o]=find2(fu2[o]);
    return fu2[o];    
}
int main()
{
    scanf("%d%d%d",&n,&m,&k);
    if(n==1||m==1)
    {
        printf("0");
                return 0;
    }
    for(i=1;i<=n+m;i++)fu[i]=fu2[i]=i;//fu 
fu2[1]=fu2[1+n];
fu[1]=fu[1+n];
int lin=-1;
    for(i=1;i<=k;i++)
    {
        scanf("%d%d%d",&a[i],&b[i],&c[i]);
        if(lin==-1)
        {if(a[i]==1&&b[i]==1)lin=c[i];}
        else if(a[i]==1&&b[i]==1)
        {
            printf("0");
            return 0;
        }
        b[i]+=n;            
    }    
//1,1为  0    
    if(lin!=1){for(i=1;i<=k;i++)
    {    fu2[find2(a[i])]=fu2[find2(b[i])];
        if(a[i]==1||b[i]==n+1)
        {
            if(c[i]==0)
            {
            
                fu[find(a[i])]=fu[find(b[i])];
            }else
            {
            if(bt[a[i]]>0)    
            {
                fu[find(bt[a[i]])]=find(b[i]);
            }else bt[a[i]]=b[i];
             if(bt[b[i]]>0)    
            {
                fu[find(bt[b[i]])]=find(a[i]);
            }else bt[b[i]]=a[i];            
            }
        }else
        if((a[i]&1)==0&&((b[i]-n)&1)==0)//^=1
        {
                    if(c[i]==1)
            {
                fu[find(a[i])]=fu[find(b[i])];
            }else
            {
            if(bt[a[i]]>0)    
            {
                fu[find(bt[a[i]])]=find(b[i]);
            }else bt[a[i]]=b[i];    
            if(bt[b[i]]>0)    
            {
                fu[find(bt[b[i]])]=find(a[i]);
            }else bt[b[i]]=a[i];            
            }
        }
        else
        {
                            if(c[i]==0)
            {
                fu[find(a[i])]=fu[find(b[i])];
            }else
            {
            if(bt[a[i]]>0)    
            {
                fu[find(bt[a[i]])]=find(b[i]);
            }else bt[a[i]]=b[i];
                    if(bt[b[i]]>0)    
            {
                fu[find(bt[b[i]])]=find(a[i]);
            }else bt[b[i]]=a[i];                  
            }    
        }
    }
    bool ky=1;
    for(i=1;i<=n+m;i++)
    {cx[i]=0;
        if(find(i)==find(bt[i]))
        {
            ky=0;break;
        }
    }
    cnt=-1;
    for(i=1;i<=n+m;i++)
    {
        if(cx[find2(i)]==0)
        {
        cnt++;
        cx[find2(i)]=1;            
        }        
    }
    if(ky==1)ans=ksm(2,cnt);
}  
//    cout<<cnt<<" "<<ans<<"  ";
    for(i=1;i<=n+m;i++)fu[i]=fu2[i]=i,bt[i]=0;
    fu2[1]=fu2[1+n];
    fu[1]=fu[n+1];
    //1,1为  1    
    if(lin!=0)
    {for(i=1;i<=k;i++)
    {                fu2[find2(a[i])]=fu2[find2(b[i])];

        if(a[i]==1||b[i]==n+1)
        {
            if(c[i]==1)
            {
                fu[find(a[i])]=fu[find(b[i])];
            }else
            {
            if(bt[a[i]]>0)    
            {
                fu[find(bt[a[i]])]=find(b[i]);
            }else bt[a[i]]=b[i];    
                if(bt[b[i]]>0)    
            {
                fu[find(bt[b[i]])]=find(a[i]);
            }else bt[b[i]]=a[i];            
            }
            
        }else
        if((a[i]&1)==0&&((b[i]-n)&1)==0)//^=1
        {
                    if(c[i]==0)
            {
                fu[find(a[i])]=fu[find(b[i])];
            }else
            {
            if(bt[a[i]]>0)    
            {
                fu[find(bt[a[i]])]=find(b[i]);
            }else bt[a[i]]=b[i];
                    if(bt[b[i]]>0)    
            {
                fu[find(bt[b[i]])]=find(a[i]);
            }else bt[b[i]]=a[i];                
            } 
        }
        else
        {
                            if(c[i]==1)
            {
                fu[find(a[i])]=fu[find(b[i])];
            }else
            {
            if(bt[a[i]]>0)    
            {
                fu[find(bt[a[i]])]=find(b[i]);
            }else bt[a[i]]=b[i];
                        if(bt[b[i]]>0)    
            {
                fu[find(bt[b[i]])]=find(a[i]);
            }else bt[b[i]]=a[i];                
            }    
        }
    }
bool    ky=1;
    for(i=1;i<=n+m;i++)
    {cx[i]=0;
        if(find(i)==find(bt[i]))
        {
            ky=0;break;
        }
    }
    cnt=-1;
    for(i=1;i<=n+m;i++)
    {
        if(cx[find2(i)]==0)
        {
        cnt++;
        cx[find2(i)]=1;            
        }        
    }
    if(ky==1)ans+=ksm(2,cnt),ans%=P;
}
    printf("%lld",ans);
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值