codeforces #309 553C C. Love Triangles(dfs+ 图论)

题目链接:

点击打开链接

题目大意:

给出n个点,要求构造合法的完全图,已经给出了一些边,边有红边和蓝边,其中任意三个点,连成的边合法的组合有红红红,红蓝蓝

问符合要求的完全图的数量

题目分析:

首先我们考虑三个点,可能存在的合法组合是红红红,红蓝蓝,那么如果给出其中一条边(x,y)是红,那么可以断定x,y到另外一点的颜色一定相同;

如果是蓝色,那么,x和y到另外一点的颜色一定不同,因此对于有边相连的一堆点,我们称为一个连通块,那么对于这个连通块当中点看成是和其中某一点的为dfs的起点,那么只要确定它到其他点的颜色,因为两条边颜色确定后第三条边颜色是一定的,所以就只能得到一个完全图,然而如果题中给出了x,y有边,那么就可以直接给出(1,x),(1,y)的颜色关系,(建设dfs起点为1),那么在dfs中,(1,1)一定是红色,那么根据颜色关系,可以对其他的点进行染色,存在满足所有关系的那么构成一个连通块,没有的话整个题就无解。然后分成连通块之后,对于每个连通块,只要和其他连通块建立一条边,因为两边可以确定第三边,所以其他的边都变成确定的。所以最后就是连通块个数k,结果为2^k

#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <vector>
#define MAX 100007

using namespace std;

vector< pair<int,int> > e[MAX];
int vis[MAX];
const int mod = 1e9+7;
int ans;

void dfs ( int x )
{
    for ( int i = 0 ; i < e[x].size(); i++ )
    {
        int v = e[x][i].first;
        int t = e[x][i].second;
        if ( vis[v] == -1 )
        {
            if ( t == 1 )
                vis[v] = vis[x];
            else 
                vis[v] = 1 - vis[x];
            dfs ( v );
        }
        if ( t == 1 )
        {
            if ( vis[v] != vis[x] )
                ans = 0;
        }
        else 
        {
            if ( vis[v] == vis[x] )
                ans = 0;
        }
    }
}


int main ( )
{
    int n,m,a,b,c;
    while ( ~scanf ( "%d%d" , &n , &m ) )
    {
        for ( int i = 0 ; i < m ; i++ )
        {
            scanf ( "%d%d%d" , &a , &b , &c );
            e[a].push_back ( make_pair(b,c) );
            e[b].push_back ( make_pair(a,c) );
        }
        ans = (mod+1)/2;
        memset ( vis , -1 , sizeof ( vis ) );
        for ( int i = 1 ; i <= n ; i++ )
        {
            if ( vis[i] == -1 )
            {
                ans = (ans+ans)%mod;
                vis[i] = 0;
 
               dfs (i);
            }
        }
        printf ( "%d\n" , ans );
    }
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值