poj2230 Watchcow(欧拉回路)
题目大意
有一个由n个点和m条边组成的无向图。
让你从节点1出发,每条边恰好从正反两个方向走一遍。
输出任意一种方案。
解题思路
那这题和欧拉回路对比一下,发现欧拉回路是每个边直走一次,所以有以下代码。
vis[e] = vis[e ^ 1] = 1;
其中标记了当的方向和反边。
而这题是从两个方向走,所以对每个边只要标记以下当前的方向,每个边就会遍历两遍。
代码如下:
#include <iostream> #include <cstdio> #include <algorithm> #include <cstring> #include <vector> #include <stack> #define rep(x, l, r) for(int x = l; x <= r; x++) #define repd(x, r, l) for(int x = r; x >= l; x--) #define clr(x, y) memset(x, y, sizeof(x)) #define all(x) x.begin(), x.end() #define pb push_back #define mp make_pair #define MAXN 100005 #define MAXM 1000005 #define fi first #define se second #define SZ(x) ((int)x.size()) using namespace std; typedef long long LL; typedef vector<int> vi; typedef pair<int, int> pii; const int INF = 0x3f3f3f3f; const int p = 10000007; int lowbit(int x){ return x & -x; } int fast_power(int a, int b){ int x; for(x = 1; b; b >>= 1){ if(b & 1) x = 1ll * x * a % p; a = 1ll * a * a % p; } return x; } stack<int> sta; int n, cnt, tot; int head[MAXN], nxt[MAXM], to[MAXM]; int ans[2 * MAXN]; bool vis[MAXM]; void init(){ cnt = 0; clr(head, -1); } void add(int u, int v){ nxt[cnt] = head[u]; head[u] = cnt; to[cnt] = v; cnt++; } void euler(){ sta.push(1); while(!sta.empty()){ int u = sta.top(), e = head[u]; while(e != -1&& vis[e]) e = nxt[e]; if(e != -1){ int v = to[e]; sta.push(v); vis[e] = 1; head[u] = nxt[e]; } else{ sta.pop(); ans[++tot] = u; } } } int main(){ init(); int m; scanf("%d%d", &n, &m); rep(i, 1, m){ int u, v; scanf("%d%d", &u, &v); add(u, v), add(v, u); } euler(); repd(i, tot, 1) printf("%d\n", ans[i]); return 0; }