1. 程式人生 > >codeforces723E One-Way Reform(尤拉通路)

codeforces723E One-Way Reform(尤拉通路)

第一次打線上賽,1456分來著,感覺自己模擬題做的不怎麼樣,總是想複雜,而且寫程式碼慢的要死,這套題說實話還算簡單,但只A了兩道,其他的題都很基礎,這題尤拉通路我剛好不會,所以寫一下。

題意:

n個城市之間m條雙向道路,現在把雙向道路變成單向,求讓出入度相同的城市最多的路線圖。

要點:

這題就是個尤拉通路問題,因為要把雙向變成單向,所以原本的出度如果是奇數,說明這個頂點的入度和出度不相等,原本是偶數的直接就是相等的,所以最大城市數就是n-出度奇數個數。現在問題是怎麼輸出最後的路線圖,我們引入一個新頂點,將所有出度為奇數的點與新頂點連線,這樣圖中所有點的出入度都相等。這裡說明一下出度為奇數的點一定是偶數個,因為一條邊對應兩個點,這裡多一個那邊就少一個。這樣對整個圖進行dfs輸出歐拉回路即可。

#include<iostream>
#include<set>
#include<algorithm>
using namespace std;
set<int> edge[210];//用set方便之後刪除邊
int t, n, m;

void dfs(int i)
{
	if (edge[i].empty())//如果當前頂點沒有出去的邊就返回
		return;
	int x = *edge[i].begin();
	edge[i].erase(x);//將經過的邊消除
	edge[x].erase(i);		
	if (i != n + 1 && x != n + 1)//新加入的點不參與輸出
		printf("%d %d\n", i, x);
	dfs(x);
}

int main()
{
	int i, j;
	scanf("%d", &t);
	while (t--)
	{
		scanf("%d%d", &n, &m);
		for (i = 0; i < 210; i++)
			edge[i].clear();
		int u, v;
		for (i = 1; i <= m; i++)
		{
			scanf("%d%d", &u, &v);
			edge[u].insert(v);
			edge[v].insert(u);
		}
		for(i=1;i<=n;i++)
			if (edge[i].size() & 1)
			{
				edge[i].insert(n + 1);
				edge[n + 1].insert(i);
			}
		printf("%d\n", n-edge[n + 1].size());
		for (i = 1; i <= n; i++)
		{
			while (!edge[i].empty())
			{
				dfs(i);
			}
		}
	}
	return 0;
}