本来想下午做完了周末好好玩,结果尼玛做了一晚上...
题意:
亚瑟王要在圆桌上召开骑士会议,为了不引发骑士之间的冲突,并且能够让会议的议题有令人满意的结果,每次开会前都必须对出席会议的骑士有如下要求:
1、 相互憎恨的两个骑士不能坐在直接相邻的2个位置;
2、 出席会议的骑士数必须是奇数,这是为了让投票表决议题时都能有结果。
如果出现有某些骑士无法出席所有会议(例如这个骑士憎恨所有的其他骑士),则亚瑟王为了世界和平会强制把他剔除出骑士团。
现在给定准备去开会的骑士数n,再给出m对憎恨对(表示某2个骑士之间使互相憎恨的),问亚瑟王至少要剔除多少个骑士才能顺利召开会议
( 我找网上的题意,自己说不清楚 )
题解:
1,将图求反,就是把有的边去掉,将没有的添上
2,找到双连通块
3,在双连通块中找是否存在奇圈,若存在则块中的骑士都可以开会的
4,统计有多少骑士不能存在在大于1的奇圈中的
代码:
#include <iostream>
#include <cstring>
#include <cstdio>
#include <stack>
#include <queue>
using namespace std ;
const int MAXN = 1005 ;
const int MAXM = MAXN * MAXN * 2 ;
struct type
{
int end , next ;
} ;
type edge[MAXM] ;
int head[MAXN] , Count , mark[MAXN] ;
int low[MAXN] , dfn[MAXN] , vis[MAXN] ;
int map[MAXN][MAXN] , num[MAXN] , belone[MAXN] ;
int color[MAXN] ;
stack < int > Stack ;
void addedge( int start , int end )
{
edge[Count].end = end ;
edge[Count].next = head[start] ;
head[start] = Count ++ ;
}
int bfs( int cur , int from )
{
memset( color , -1 , sizeof( color ) ) ;
queue < int > q ;
q.push( cur ) ;
color[cur] = 0 ;
while( !q.empty() )
{
int temp = q.front() ;
q.pop() ;
for( int i = head[temp] ; i != -1 ; i = edge[i].next )
{
int end = edge[i].end ;
if( belone[end] != from ) continue ;
if( color[end] == 1 - color[temp] ) continue ;
if( color[end] == -1 )
{
color[end] = 1 - color[temp] ;
q.push( end ) ;
}
else if( color[end] == color[temp] ) return 1 ;
}
}
return 0 ;
}
void tarjan_dfs( int cur , int father , int & cnt , int & Time )
{
Stack.push( cur ) ;
dfn[cur] = low[cur] = Time ++ ;
vis[cur] = 1 ;
for( int i = head[cur] ; i != -1 ; i = edge[i].next )
{
int end = edge[i].end ;
if( end == father ) continue ;
if( !vis[end] )
{
tarjan_dfs( end , cur , cnt , Time ) ;
low[cur] = min( low[cur] , low[end] ) ;
if( dfn[cur] <= low[end] )
{
int temp , Cnt = 0 ;
cnt ++ ;
do
{
temp = Stack.top() ;
Stack.pop() ;
num[Cnt] = temp ;
belone[temp] = cnt ;
Cnt ++ ;
}while( temp != end ) ;
num[Cnt] = cur ;
belone[cur] = cnt ;
Cnt ++ ;
if( bfs( cur , cnt ) ){
for( int j = 0 ; j < Cnt ; j ++ ){
mark[num[j]] = 1 ;
}
}
}
}
else low[cur] = min( low[cur] , dfn[end] ) ;
}
}
int tarjan( int n )
{
int Time = 0 , cnt = 0 ;
memset( dfn , 0 , sizeof( dfn ) ) ;
memset( low , 0 , sizeof( low ) ) ;
memset( vis , 0 , sizeof( vis ) ) ;
memset( num , 0 , sizeof( num ) ) ;
memset( belone , -1 , sizeof( belone ) ) ;
for( int i = 1 ; i <= n ; i ++ ){
if( !vis[i] ) tarjan_dfs( i , -1 , cnt , Time ) ;
}
return cnt ;
}
int main()
{
int m , n , i , j ;
int start , end ;
while( scanf( "%d%d" , & n , & m ) && n && m )
{
memset( head , -1 , sizeof( head ) ) ;
memset( map , 0 , sizeof( map ) ) ;
memset( mark , 0 , sizeof( mark ) ) ;
Count = 0 ;
while( m -- )
{
scanf( "%d%d" , & start , & end ) ;
map[start][end] = 1 ;
map[end][start] = 1 ;
}
for( i = 1 ; i <= n ; i ++ )
for( j = 1 ; j <= n ; j ++ )
{
if( i == j ) continue ;
if( !map[i][j] ) addedge( i , j ) ;
}
int ans = 0 ;
int temp = tarjan( n ) ;
for( i = 1 ; i <= n ; i ++ )
if( mark[i] == 0 ) ans ++ ;
printf( "%d\n" , ans ) ;
}
return 0 ;
}
代码修修改改好多次才过的,所以很挫....