AcWing 1124. 骑马修栅栏


题目传送门

  • 本题数据量较小,可以使用邻接矩阵
  • 要求输出最小字典序,我们需要保证由小点出发,一路上从小枚举到大
  • 考查无向图求欧拉路径的办法

一、邻接矩阵模板

#include 
using namespace std;

const int N = 510;

int n = 500, m;
int g[N][N];      //邻接矩阵
vector path; //欧拉路径
int d[N];         //度数
void dfs(int u) {
    //我们在遍历的时候,把走过的路删掉,这样就不会重复走了,而且省去了反复横跳的风险
    for (int i = 1; i <= n; i++)  //枚举每个点
        if (g[u][i]) {            //如果u->i存在一条边
            g[u][i]--, g[i][u]--; //那么我们删除掉正向边和反向边
            dfs(i);               //继续搜索
        }
    path.push_back(u); //记录这个点
}

int main() {
    cin >> m;
    while (m--) {
        int a, b;
        cin >> a >> b;
        g[a][b]++, g[b][a]++; //邻接矩阵记录无向边
        d[a]++, d[b]++;       //记录无向图的度数
    }

    //下面这样去费劲找到第一个可行的度数为奇数的点,是为了最小字典序
    //较小编号作为起点
    int start = 1;               //默认从1号点出发
    while (!d[start]) start++;   //如果是孤立点,那么继续尝试其它点
    for (int i = 1; i <= n; i++) //尝试找到度数为奇数的点
        if (d[i] % 2) {
            start = i;
            break;
        }
    //无向图开始查找欧拉路径
    dfs(start);
    //输出欧拉路径
    for (int i = path.size() - 1; i >= 0; i--) printf("%d\n", path[i]);
    return 0;
}

二、邻接表解法

#include 
using namespace std;

const int N = 5e3 + 10;
typedef pair PII;
int n = 500, m;
vector path;
bool st[N];
int d[N];
int h[N], e[N], ne[N], idx;
void add(int a, int b) {
    e[idx] = b, ne[idx] = h[a], h[a] = idx++;
}

void dfs(int u) {
    vector a;
    for (int i = h[u]; ~i; i = ne[i]) a.push_back({e[i], i});
    sort(a.begin(), a.end()); //从小到大排序
    for (int i = 0; i < a.size(); i++) {
        int edge = a[i].second;
        if (st[edge] || st[edge ^ 1]) continue;
        st[edge] = st[edge ^ 1] = true;
        dfs(a[i].first);
    }
    path.push_back(u);
}
int main() {
    memset(h, -1, sizeof h);
    cin >> m;
    while (m--) {
        int a, b;
        cin >> a >> b;
        add(a, b), add(b, a);
        d[a]++, d[b]++;
    }

    int start = 1;
    while (!d[start]) start++;
    for (int i = 1; i <= n; i++)
        if (d[i] & 1) {
            start = i;
            break;
        }
    dfs(start);
    for (int i = path.size() - 1; i >= 0; i--) cout << path[i] << endl;
    return 0;
}

相关