题目链接http://codeforces.com/problemset/problem/723/E
PS:这个题花了我一下午 呜呜呜。参考了别人的文章最终搞明白了原理 原文好多我不知道的东西 就一点一点查明白,到最后的AC 很是欣慰啊!
题意:
给你一个图:1无向图 2 每一对点之间只存在一条路径 3.不存在自己到自己的路径
让你求出 入度和出度相等的城市 然后输出所有的联通路径 每条边只能出现一次
解题思路:
找到出度和出度相等的城市很好找 关键是你要输出这个路径 这个路径不是随便输出的 因为如果处理不好度为奇数的城市 你会把一条完整的路径給分开 所以这就用得到了 欧拉回路的思想了。
假设一个图的度为M (必定为偶数) 因为每一条边的度为2 。 那么奇数度的城市 为k个 那么k必为偶数
为什么呢 因为总度为偶数。。。。所以我们只需要添加一个城市 让奇数度的点与他相连 那么就保证了整个图上的每一个点的度为偶数 那么必定 有一条回路 包含了 新加的这个点 那么我们只需要再打印的时候过滤这个点就好了 那么这条路径就是完整而且没有被分割的 .。。
这个题用到了dfs+欧拉回路(我只学会了这一种 如果还有其他的方法我会后续贴上)
AC代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<set>
using namespace std;
const int maxn= 200+10;
set<int> map1[maxn];//此图为稀疏图 所以我们用邻接矩阵存储
int du[maxn];//保存了每一个城市的度
int tc,n,m;
void init()
{
memset(du,0,sizeof(du));
for(int i=0;i<maxn;i++)
map1[i].clear();//清空集合内容
}
void dfs(int u)
{
while(map1[u].size())
{
int v=*map1[u].begin();
map1[u].erase(v);
map1[v].erase(u);
if(u!=n+1&&v!=n+1)//如果这条边包含我们自己加上的那个点 就过滤
printf("%d %d\n",u,v);
dfs(v);
}
}
int main()
{
int u,v;
cin>>tc;
while(tc--)
{
init();
cin>>n>>m;
while(m--)
{
cin>>u>>v;
du[u]++;//记录这个城市的度
du[v]++;
map1[u].insert(v);
map1[v].insert(u);
}
int c_js_du=0;
for(int i=1;i<=n;i++)
{
if(du[i]&1)//这就是骚操作了 按位与 只要是奇数 那么二进制最后一位必为1
{
c_js_du++;
map1[i].insert(n+1);
map1[n+1].insert(i);
}
}
printf("%d\n",n-c_js_du);
for(int i=1;i<=n;i++)
dfs(i);//因为可能存在不联通的边 所以我们每一个点都要遍历一遍
}
return 0;
}