【模板】Tarjan求割点(无向图)


D. 备用交换机

题目描述

n个城市之间有通讯网络,每个城市都有通讯交换机,直接或间接与其它城市连接。因电子设备容易损坏,需给通讯点配备备用交换机。但备用交换机数量有限,不能全部配备,只能给部分重要城市配置。于是规定:如果某个城市由于交换机损坏,不仅本城市通讯中断,还造成其它城市通讯中断,则配备备用交换机。请你根据城市线路情况,计算需配备备用交换机的城市个数,及需配备备用交换机城市的编号。

输入格式

输入文件有若干行 第一行,一个整数n,表示共有n个城市(2<=n<=100) 下面有若干行,每行2个数a、b,a、b是城市编号,表示a与b之间有直接通讯线路。

输出格式

输出文件有若干行 第一行,1个整数m,表示需m个备用交换机,下面有m行,每行有一个整数,表示需配备交换机的城市编号,输出顺序按编号由小到大。如果没有城市需配备备用交换机则输出0。

样例

样例输入

7
1 2
2 3
2 4
3 4
4 5
4 6
4 7
5 6
6 7

样例输出

2
2
4

数据范围与提示

数据中可能存在森林

#include
#include

namespace bikuhiku{
    template  _T gtr(_T &_compare_x,_T &_compare_y) {
        return _compare_x > _compare_y ? _compare_x : _compare_y;
    }
    template  _T les(_T &_compare_x,_T &_compare_y) {
        return _compare_x < _compare_y ? _compare_x : _compare_y;
    }
    template  void get_int(_T &_data_x) {
        int _signal = 1;
        char _get_c;
        _data_x = 0;
        for(_get_c = getchar();_get_c < '0'||_get_c > '9';_get_c = getchar()) if(_get_c == '-') _signal = -1;
        for(;_get_c >= '0'&&_get_c <= '9';_get_c = getchar()) _data_x = (_data_x<<3)+(_data_x<<1)+(_get_c^48);
        _data_x *= _signal;
        return;
    }
    template  void put_int(_T _data_x) {
        if(_data_x > 9) put_int(_data_x/10);
        putchar((_data_x%10)^48);
        return;
    }
    int _ = 0;
    int _Use = 1;
}//申请一块命名空间;
using namespace bikuhiku;
using namespace std;

const int z = 128;
int m, n, ans;
int s, e;

struct line{
	int t, next;
} edge[z*128];
int cnt, head[z], od[z];
void adline(int &f,int &t) {
	edge[++cnt].next = head[f];
	edge[cnt].t = t;
	head[f] = cnt;
	return;
}

stack stk;
int dfn[z], low[z], time, cvnum;
bool cut_vertex[z];
void tarjan(int &u,int &root) {
	dfn[u] = low[u] = ++time;
	int sub = 0;
	for(int i = head[u];i;i = edge[i].next) {
		if(!dfn[edge[i].t]) {
			++sub;
			tarjan(edge[i].t,root);
			low[u] = les(low[u],low[edge[i].t]);
			if(dfn[u] <= low[edge[i].t]) 
				if(u != root||sub > 1) {
					if(!cut_vertex[u]) ++cvnum;
					cut_vertex[u] = true;
				}
		} else {
			low[u] = les(low[u],dfn[edge[i].t]);
		}
	}
	return;
} 

int main() {
	get_int(n);
	while(scanf("%d %d",&s,&e) != EOF) {
		adline(s,e);
		adline(e,s);
	}
	for(int i = 1;i <= n;++i) 
		if(!dfn[i]) tarjan(i,i);
	put_int(cvnum);
	putchar(10);
	for(int i = 1;i <= n;++i) 
		if(cut_vertex[i]) {
			put_int(i);
			putchar(10);
		}
	return 0^_^0;
}