URAL 1389 Roadworks

//在一个图中选取尽可能多没有相同结点的边
#include <stdio.h>
#define MAX 100000

typedef struct Road{
	int to;
	int next;
}Road;
Road toArray[MAX * 2];
int numOfTos;
int toLastAdded[MAX + 1];
//degree[city]表示与城市city相连的路中,有可能被封的路的数量
int degree[MAX + 1];
int queue[MAX + 1];
int head, tail;
int blocked[MAX + 1];
int roadsBlocked[MAX + 1][2];
int numOfRoadsBlocked;

void addRoad(int from, int to){
	numOfTos++;
	int toNum = numOfTos;
	toArray[toNum].to = to;
	toArray[toNum].next = toLastAdded[from];
	toLastAdded[from] = toNum;
}

int numOfCities, numOfRoads;
int main(){

	freopen("input.txt", "r", stdin);
	scanf("%d%d", &numOfCities, &numOfRoads);
	int road;
	for (road = 1; road <= numOfRoads; road++){
		int from, to;
		scanf("%d%d", &from, &to);
		addRoad(from, to);
		addRoad(to, from);
		degree[to]++;
		degree[from]++;
	}

	int city;
	//先把进出只有一条路的城市给封了,也就是度为1的顶点的连接边给封了
	for (city = 1; city <= numOfCities; city++)
		if (degree[city] == 1)
			queue[tail++] = city;
	
	while (head < tail){
		int cityPoped = queue[head++];
		if (blocked[cityPoped])
			continue;
		blocked[cityPoped] = 1;
		int cityBlocked = 0;
		int toIndex;
		for (toIndex = toLastAdded[cityPoped]; toIndex != 0; toIndex = toArray[toIndex].next){
			int city = toArray[toIndex].to;
			if (blocked[city] == 0){
				blocked[city] = 1;
				numOfRoadsBlocked++;
				roadsBlocked[numOfRoadsBlocked][0] = cityPoped;
				roadsBlocked[numOfRoadsBlocked][1] = city;
				cityBlocked = city;
				break;
			}
		}
		if (cityBlocked != 0){
			for (toIndex = toLastAdded[cityBlocked]; toIndex != 0; toIndex = toArray[toIndex].next){
				int city = toArray[toIndex].to;
				if (blocked[city] == 0){
					//因为城市cityPoped和城市cityBlocked之间的路已经封了,所以城市cityBlocked和城市city之间的路不能再封(因为与城市cityBlocked相连的路最多只能封一条),也就是说在与城市city相连的这些路中,有可能被封的路少了一个,也就是度减1
					degree[city]--;
					if (degree[city] == 1)
						queue[tail++] = city;
				}
			}	
		}
	}

	printf("%d\n", numOfRoadsBlocked);
	int roadIndex;
	for (roadIndex = 1; roadIndex <= numOfRoadsBlocked; roadIndex++)
		printf("%d %d\n", roadsBlocked[roadIndex][0], roadsBlocked[roadIndex][1]);
	printf("\n");

	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值