題目的意思是要我們?nèi)サ糇疃嗟倪吺箞D還是連通的,同了強(qiáng)連通分支的算法。如下:
#include <stdio.h>

const int LEN = 5005;

struct HEAD


{
int state; //搜索狀態(tài)
int fa; //在堆棧中的位置
int du;
int next;
int last;
};
HEAD head1[LEN]; //原圖
HEAD head2[LEN]; //新圖

struct NODE


{
int num;
int other; //記錄還有一條邊的位置
int used; //是否可用
int next;
}node[LEN*8];
int next_n;

int bridge[LEN/2]; //記錄橋的位置
int next_b;

void init_m ( HEAD head[], int n )


{

for ( int i=0; i<n; i++ )

{
head[i].state = 0;
head[i].next = -1;
head[i].du = 0;
}
}

inline void ins ( HEAD head[], int a, int b )


{

node[next_n].next = -1;
node[next_n].num = b;
next_n ++;

if ( head[a].next==-1 )
head[a].next = next_n-1;
else
node[ head[a].last ].next = next_n-1;
head[a].last = next_n-1;
head[a].du ++;
}

int ser ( HEAD head[], int far, int p, int depth ) //找橋


{

head[p].state = 1;

int fa = depth;
head[p].fa = depth;
for ( int i=head[p].next; i!=-1; i=node[i].next )

{
int e = node[i].num;
if ( head[e].state==1&&e!=far )

{
if ( fa>head[e].fa )
fa = head[e].fa;
}
else if ( head[e].state==0 )

{
int sonfa = ser ( head, p, e, depth+1 );
if ( sonfa>depth )
bridge[next_b++] = i;
if ( fa>sonfa )
fa = sonfa;
}
}
head[p].state = 2;

return fa;
}

void ser2 ( HEAD head[], int p, int color )


{

head[p].state = 1;

head[p].fa = color;
for ( int i=head[p].next; i!=-1; i=node[i].next )

{
int e = node[i].num;
if ( !node[i].used&&!head[e].state )
ser2 ( head, e, color );
}

head[p].state = 2;
}

int work ( int n )


{

//找橋
next_b = 0;
ser ( head1, -1, 0, 0 );
for ( int i=0; i<next_b; i++ )

{
int p = bridge[i];
node[p].used = 1;
node[ node[p].other ].used = 1;
}
//求連通分塊
for ( int i=0; i<n; i++ )
head1[i].state = 0;
int color = 0;
for ( int i=0; i<n; i++ )

{
if ( !head1[i].state )
ser2 ( head1, i, color++ );
}
//建圖
init_m ( head2, color );
for ( int i=0; i<n; i++ )
for ( int j=head1[i].next; j!=-1; j=node[j].next )

{
int a = i;
int b = node[j].num;
if ( head1[a].fa!=head1[b].fa )

{
ins ( head2, head1[a].fa, head1[b].fa );
}
}
int ans = 0;
for ( int i=0; i<color; i++ )

{
if ( head2[i].du==1 )
ans ++;
}
return (ans+1)/2;
}

int main ()


{

int n, m;
scanf ( "%d%d", &n, &m );
next_n = 0;
init_m ( head1, n );
for ( int i=0; i<m; i++ )

{
int a, b;
scanf ( "%d%d", &a, &b );
ins ( head1, a-1, b-1 );
node[next_n-1].other = next_n;
ins ( head1, b-1, a-1 );
node[next_n-1].other = next_n-2;
}

printf ( "%d\n", work ( n ) );
return 0;
}
#include <stdio.h>
const int LEN = 5005;
struct HEAD 

{
int state; //搜索狀態(tài)
int fa; //在堆棧中的位置
int du;
int next;
int last;
};
HEAD head1[LEN]; //原圖
HEAD head2[LEN]; //新圖
struct NODE

{
int num;
int other; //記錄還有一條邊的位置
int used; //是否可用
int next;
}node[LEN*8];
int next_n;
int bridge[LEN/2]; //記錄橋的位置
int next_b; 
void init_m ( HEAD head[], int n )

{
for ( int i=0; i<n; i++ )
{
head[i].state = 0;
head[i].next = -1;
head[i].du = 0;
}
}
inline void ins ( HEAD head[], int a, int b )

{
node[next_n].next = -1;
node[next_n].num = b;
next_n ++;
if ( head[a].next==-1 )
head[a].next = next_n-1;
else
node[ head[a].last ].next = next_n-1;
head[a].last = next_n-1;
head[a].du ++;
}
int ser ( HEAD head[], int far, int p, int depth ) //找橋

{
head[p].state = 1;
int fa = depth;
head[p].fa = depth;
for ( int i=head[p].next; i!=-1; i=node[i].next )
{
int e = node[i].num;
if ( head[e].state==1&&e!=far )
{
if ( fa>head[e].fa )
fa = head[e].fa;
}
else if ( head[e].state==0 )
{
int sonfa = ser ( head, p, e, depth+1 );
if ( sonfa>depth )
bridge[next_b++] = i;
if ( fa>sonfa )
fa = sonfa;
}
}
head[p].state = 2;
return fa;
}
void ser2 ( HEAD head[], int p, int color )

{
head[p].state = 1;
head[p].fa = color;
for ( int i=head[p].next; i!=-1; i=node[i].next )
{
int e = node[i].num;
if ( !node[i].used&&!head[e].state )
ser2 ( head, e, color );
}
head[p].state = 2;
}
int work ( int n )

{
//找橋
next_b = 0;
ser ( head1, -1, 0, 0 );
for ( int i=0; i<next_b; i++ )
{
int p = bridge[i];
node[p].used = 1;
node[ node[p].other ].used = 1;
}
//求連通分塊
for ( int i=0; i<n; i++ )
head1[i].state = 0;
int color = 0;
for ( int i=0; i<n; i++ )
{
if ( !head1[i].state )
ser2 ( head1, i, color++ );
}
//建圖
init_m ( head2, color );
for ( int i=0; i<n; i++ )
for ( int j=head1[i].next; j!=-1; j=node[j].next )
{
int a = i;
int b = node[j].num;
if ( head1[a].fa!=head1[b].fa )
{
ins ( head2, head1[a].fa, head1[b].fa );
}
}
int ans = 0;
for ( int i=0; i<color; i++ )
{
if ( head2[i].du==1 )
ans ++;
}
return (ans+1)/2;
}
int main ()

{
int n, m;
scanf ( "%d%d", &n, &m );
next_n = 0;
init_m ( head1, n );
for ( int i=0; i<m; i++ )
{
int a, b;
scanf ( "%d%d", &a, &b );
ins ( head1, a-1, b-1 );
node[next_n-1].other = next_n;
ins ( head1, b-1, a-1 );
node[next_n-1].other = next_n-2;
}
printf ( "%d\n", work ( n ) );
return 0;
}

