题目描述
There are n cities and m two-way roads in Berland, each road connects two cities. It is known that there is no more than one road connecting each pair of cities, and there is no road which connects the city with itself. It is possible that there is no way to get from one city to some other city using only these roads.
The road minister decided to make a reform in Berland and to orient all roads in the country, i.e. to make each road one-way. The minister wants to maximize the number of cities, for which the number of roads that begins in the city equals to the number of roads that ends in it.
算法思路
比赛的时候手速太慢,结果没有及时交上去,囧。。。。
题目很简单,将一个无向图转化成一个有向图,并且尽量让入度等于出度的节点尽量多。并且要求输出一个解。
首先我们考虑两种极端的情况,如果在一个联通分量中,所有的点度数都是偶数,那么我们很快就可以知道这是一个欧拉图,所有的点经过一种转化都可以成为入度等于出度的点。如果一个联通分量中所有的点度数都是奇数,那么则没有一个点经过转化之后入度可以等于出度。
那么我们考虑一个图当中的点有些的度数是偶数,有些的度数是奇数的情况。我们可以得到下面的结论:
1. 奇数度的结点数目为偶数,由握手定理可得。
2. 从一个奇数度的结点构造一条路径,其终点也一定是奇数度的结点
所以我们立刻可以想到,在一条路径中,离开一个结点的次数一定等于进入这个结点的次数。所以使用DFS,解决。
代码
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>
using namespace std;
#define MAXN 205
vector<int>ans;
int grid[MAXN][MAXN];
int deg[MAXN];
int n,m,t,o;
void Dfs(int cur)
{
//cout << cur << endl;
int i;
for(i=1;i<=n;i++){
if(grid[cur][i]){
grid[cur][i] = grid[i][cur] = 0;
deg[cur]--;
deg[i]--;
ans.push_back(cur);
ans.push_back(i);
Dfs(i);
break;
}
}
return;
}
int main()
{
//freopen("input","r",stdin);
int i,tmp1,tmp2;
scanf("%d",&t);
while(t--){
memset(grid,0,sizeof(grid));
memset(deg,0,sizeof(deg));
ans.clear();
o = 0;
scanf("%d%d",&n,&m);
for(i=0;i<m;i++){
scanf("%d%d",&tmp1,&tmp2);
grid[tmp1][tmp2] = 1;
grid[tmp2][tmp1] = 1;
deg[tmp1]++;
deg[tmp2]++;
}
for(i=1;i<=n;i++)
if(deg[i]&1)o++;
for(i=1;i<=n;i++)
if(deg[i]&1)Dfs(i);
for(i=1;i<=n;i++)
if(deg[i])Dfs(i);
printf("%d\n",n-o);
for(i=0;i<ans.size();i+=2){
printf("%d %d\n",ans[i],ans[i+1]);
}
}
return 0;
}