Codeforces Round #309 (Div. 2) E DFS 染色 + 快速乘



链接:戳这里


E. Love Triangles
time limit per test2 seconds
memory limit per test256 megabytes
inputstandard input
outputstandard output
There are many anime that are about "love triangles": Alice loves Bob, and Charlie loves Bob as well, but Alice hates Charlie. You are thinking about an anime which has n characters. The characters are labeled from 1 to n. Every pair of two characters can either mutually love each other or mutually hate each other (there is no neutral state).

You hate love triangles (A-B are in love and B-C are in love, but A-C hate each other), and you also hate it when nobody is in love. So, considering any three characters, you will be happy if exactly one pair is in love (A and B love each other, and C hates both A and B), or if all three pairs are in love (A loves B, B loves C, C loves A).

You are given a list of m known relationships in the anime. You know for sure that certain pairs love each other, and certain pairs hate each other. You're wondering how many ways you can fill in the remaining relationships so you are happy with every triangle. Two ways are considered different if two characters are in love in one way but hate each other in the other. Print this count modulo 1 000 000 007.

Input
The first line of input will contain two integers n, m (3 ≤ n ≤ 100 000, 0 ≤ m ≤ 100 000).

The next m lines will contain the description of the known relationships. The i-th line will contain three integers ai, bi, ci. If ci is 1, then ai and bi are in love, otherwise, they hate each other (1 ≤ ai, bi ≤ n, ai ≠ bi, ).

Each pair of people will be described no more than once.

Output
Print a single integer equal to the number of ways to fill in the remaining pairs so that you are happy with every triangle modulo 1 000 000 007.

Examples
input
3 0
output
4
input
4 4
1 2 1
2 3 1
3 4 0
4 1 0
output
1
input
4 4
1 2 1
2 3 1
3 4 0
4 1 1
output
0
Note
In the first sample, the four ways are to:

Make everyone love each other
Make 1 and 2 love each other, and 3 hate 1 and 2 (symmetrically, we get 3 ways from this).
In the second sample, the only possible solution is to make 1 and 3 love each other and 2 and 4 hate each other.


题意:

给出n个点m条边,每条边的关系是点u,v相互喜欢或者讨厌。

当a喜欢b,b喜欢c,那么a喜欢c。当a喜欢b,b讨厌c,那么a讨厌c。

现在要求任意三个点都确定相互之间的关系。有些关系没有给出,你需要计算有多少种这样的关系图满足给出的点之间的关系的条件


思路:

每个点都需要连出去n-1条关系,假设当前节点是1,(1,.x)和(1,y)的关系确立了,那么(x,y)关系也就确立了。

现在我们知道(x,y)的关系,所以可以DFS染色去更新(1,x)(1,y)的关系。不满足情况则为0

DFS更新每个没有染色过的节点,这样n个点会分成cnt块,每块都需要跟节点1确定关系。所以节点1可以讨厌当前块或者喜欢当前块。方案数就是2^(cnt-1)


代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<string>
#include<vector>
#include <ctime>
#include<queue>
#include<set>
#include<map>
#include<stack>
#include<iomanip>
#include<cmath>
#define mst(ss,b) memset((ss),(b),sizeof(ss))
#define maxn 0x3f3f3f3f
#define MAX 1000100
///#pragma comment(linker, "/STACK:102400000,102400000")
typedef long long ll;
typedef unsigned long long ull;
#define INF (1ll<<60)-1
#define mod 1000000007
using namespace std;
int n,m;
struct edge{
    int v,next,w;
}e[200100];
int head[100100],tot=0;
void Add(int u,int v,int w){
    e[tot].v=v;
    e[tot].next=head[u];
    e[tot].w=w;
    head[u]=tot++;
}
int vis[100100],color[100100],flag=0;
void DFS(int u,int fa){
    vis[u]=1;
    for(int i=head[u];i!=-1;i=e[i].next){
        int v=e[i].v;
        if(v==fa) continue;
        if(!vis[v]){
            if(e[i].w==1) color[v]=color[u];
            else color[v]=color[u]^1;
            DFS(v,u);
        }
        if(e[i].w==0){
            if(color[u]==color[v]){
                flag=1;
                return ;
            }
        } else {
            if(color[u]!=color[v]){
                flag=1;
                return ;
            }
        }
    }
}
ll qpow(ll a,int b){
    ll ans=1;
    while(b){
        if(b%2==1) ans=ans*a%mod;
        a=a*a%mod;
        b/=2;
    }
    return ans;
}
int main(){
    mst(head,-1);
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;i++){
        int u,v,w;
        scanf("%d%d%d",&u,&v,&w);
        Add(u,v,w);
        Add(v,u,w);
    }
    int cnt=0;
    for(int i=1;i<=n;i++){
        if(!vis[i]){
            cnt++;
            color[i]=1;
            DFS(i,0);
            if(flag) {
                cout<<0<<endl;
                return 0;
            }
        }
    }
    ll ans=qpow(2LL,cnt-1);
    printf("%I64d\n",ans);
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值