1. 程式人生 > >codeforces #309 553C C. Love Triangles(dfs+ 圖論)

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 );
    }
}