题目链接:
题目大意:
给出一些家庭,家庭中有夫妻,然后有些人之间有矛盾,是不能一起一起开会的,那么这些家庭只派一个代表能不能开一个社区会议
题目分析:
因为如果存在点Ai必须选Bj,那么选了Bi也一定要选Aj,那么就出现了对称的图,因为每个强连通分量的点的值必须一致,所以任意Ai和Aj如果在同一个强连通分量中,那么就矛盾,因为Ai和Aj一定是不能相同的,如果不出现矛盾的情况,那么就是有解,出现了矛盾就是无解
代码如下:
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <vector>
#include <stack>
#define MAX 2005
using namespace std;
int mark[MAX],dfn[MAX],low[MAX],belong[MAX],times,cnt;
vector<int> e[MAX];
stack<int> s;
void tarjan ( int u )
{
dfn[u] = low[u] = ++times;
mark[u] = 1;
s.push ( u );
int len = e[u].size();
for ( int i = 0 ; i < len ; i++ )
{
int v = e[u][i];
if ( !mark[v] )
{
tarjan ( v );
low[u] = min ( low[u] , low[v] );
}
if ( mark[v] == 1 )
low[u] = min ( low[u] , dfn[v] );
}
if ( dfn[u] == low[u] )
{
int temp;
do
{
temp = s.top();
belong[temp] = cnt;
mark[temp] = 2;
s.pop();
}while ( temp != u );
cnt++;
}
}
void init ( )
{
memset ( mark , 0 , sizeof ( mark ));
for ( int i = 0 ; i < MAX ; i++ )
e[i].clear();
while ( !s.empty()) s.pop();
times = cnt = 0;
}
int n,m;
int main ( )
{
int a , b , c , d;
while ( ~scanf ( "%d%d" , &n , &m ) )
{
init();
while ( m-- )
{
scanf ( "%d%d%d%d" , &a , &b , &c , &d );
e[2*a+c].push_back ( 2*b+1-d );
e[2*b+d].push_back ( 2*a+1-c );
}
for ( int i = 0 ; i < 2*n ; i++ )
if ( !mark[i] ) tarjan ( i );
bool flag = true;
for ( int i = 0 ; i < n ; i++ )
if ( belong[i<<1] == belong[i<<1|1] )
flag = false;
puts ( flag?"YES":"NO" );
}
}