欧拉路径-欧拉回路
2017-05-04 19:45
375 查看
有向图定理:有向图D存在欧拉通路的充要条件是:
D为有向图,D的基图(就是图D对应的无向图)连通,并且每个节点的出度等于它的入度;
<或者>
除两个节点外,其他节点的出度与入度都相等,而这两个节点中,其中一个节点的出度与入度的差为1(out-in=1),另一个顶点的出度与入度之差为-1(out-in=-1)
判断欧拉路是否存在的方法:
有向图:图连通,有一个顶点出度大入度1,有一个顶点入度大出度1,其余都是出度=入度。
无向图:图连通,只有两个顶点是奇数度,其余都是偶数度的。
判断欧拉回路是否存在的方法:
有向图:图连通,所有的顶点出度=入度。
无向图:图连通,所有顶点都是偶数度。
每条边只经过一次,而且回到起点
连通(不考虑度为0的点),每个顶点度数都为偶数。
基图连通(把边当成无向边,同样不考虑度为0的点),每个顶点出度等于入度。
每条边只经过一次,不要求回到起点
连通(不考虑度为0的点),每个顶点度数都为偶数或者仅有两个点的度数为奇数。
<
4000
h3 style="margin:.8em 0px;padding:0px;font-weight:100;color:rgb(85,85,85);font-family:'microsoft yahei';line-height:35px;">
有向图:
基图连通(把边当成无向边,同样不考虑度为0的点),每个顶点出度等于入度或者有且仅有一个点的出度比入度多1,有且仅有一个点的出度比入度少1,其余的出度等于入度。
如果存在欧拉回路,一定存在欧拉路径,否则如果有且仅有两个点的(出度-入度)是奇数,那么给这两个点加边,判断是否存在欧拉回路,如果存在就一定存在欧拉路径。
D为有向图,D的基图(就是图D对应的无向图)连通,并且每个节点的出度等于它的入度;
<或者>
除两个节点外,其他节点的出度与入度都相等,而这两个节点中,其中一个节点的出度与入度的差为1(out-in=1),另一个顶点的出度与入度之差为-1(out-in=-1)
判断欧拉路是否存在的方法:
有向图:图连通,有一个顶点出度大入度1,有一个顶点入度大出度1,其余都是出度=入度。
无向图:图连通,只有两个顶点是奇数度,其余都是偶数度的。
判断欧拉回路是否存在的方法:
有向图:图连通,所有的顶点出度=入度。
无向图:图连通,所有顶点都是偶数度。
欧拉回路
每条边只经过一次,而且回到起点
无向图:
连通(不考虑度为0的点),每个顶点度数都为偶数。/* * SGU 101 */ struct Edge { int to; int next; int index; int dir; bool flag; } edge[220]; int head[10]; //前驱 int tot; void init() { memset(head, -1, sizeof((head))); tot = 0; } void addEdge(int u, int v, int index) { edge[tot].to = v; edge[tot].next = head[u]; edge[tot].index = index; edge[tot].dir = 0; edge[tot].flag = false; head[u] = tot++; edge[tot].to = u; edge[tot].next = head[v]; edge[tot].index = index; edge[tot].dir = 1; edge[tot].flag = false; head[v] = tot++; return ; } int du[10]; vector<int>ans; void dfs(int u) { for (int i = head[u]; i != -1; i = edge[i].next) { if (!edge[i].flag) { edge[i].flag = true; edge[i ^ 1].flag = true; dfs(edge[i].to); ans.push_back(i); //容器尾部插入i } } return ; } int main() { //freopen("in.txt", "r", stdin); //freopen("out.txt", "w", stdout); int n; while (cin >> n) { init(); int u, v; memset(du, 0, sizeof(du)); for (int i = 1; i <= n; i++) { cin >> u >> v; addEdge(u, v, i); du[u]++; du[v]++; } int s = -1; int cnt = 0; for (int i = 0; i <= 6; i++) { if (du[i] & 1) { cnt++; s = i; } if (du[i] > 0 && s == -1) { s = i; } } if (cnt != 0 && cnt != 2) { cout << "No solution" << endl; continue; } ans.clear(); dfs(s); if (ans.size() != n) { cout << "No solution" << endl; continue; } for (int i = 0; i < ans.size(); i++) { printf("%d ", edge[ans[i]].index); if (edge[ans[i]].dir == 0) { cout << "-" << endl; } else { cout << "+" << endl; } } } return 0; }
有向图:
基图连通(把边当成无向边,同样不考虑度为0的点),每个顶点出度等于入度。
欧拉路径
每条边只经过一次,不要求回到起点
无向图:
连通(不考虑度为0的点),每个顶点度数都为偶数或者仅有两个点的度数为奇数。/* * O(E) * INIT:adj[][]置为图的邻接表;cnt[a]为a点的邻接点数 * CALL:alpath(0); 注意:不要有自向边 */ const int V = 10000; int adj[V][V]; int idx[V][V]; int cnt[V]; int stk[V]; int top = 0; int path(int v) { for (int w; cnt[v] > 0; v = w) { stk[top++] = v; w = adj[v][--cnt[v]]; adj[w][idx[w][v]] = adj[w][--cnt[w]]; //处理的是无向图——边是双向边,删除v->w后,还要处理删除w->v } return v; } void elpath(int b, int n) { int i, j; for (i = 0; i < n; i++) { for (j = 0; j < cnt[i]; j++) { idx[i][adj[i][j]] = j; } } cout << b; for (top = 0; path(b) == b && top != 0; ) { b = stk[--top]; cout << '-' << b; } cout << endl; }
<
4000
h3 style="margin:.8em 0px;padding:0px;font-weight:100;color:rgb(85,85,85);font-family:'microsoft yahei';line-height:35px;">
有向图:
基图连通(把边当成无向边,同样不考虑度为0的点),每个顶点出度等于入度或者有且仅有一个点的出度比入度多1,有且仅有一个点的出度比入度少1,其余的出度等于入度。
/* * POJ 2337 * 给出n个小写字母组成的单词,要求将n个单词连接起来。使得前一个单词的最后一个字母和 * 后一个单词的第一个字母相同。输出字典序最小解 */ struct Edge { int to; int next; int index; bool flag; }edge[2010]; int head[30]; int tot; void init() { tot = 0; memset(head, -1, sizeof(head)); } void addEdge(int u, int v, int index) { edge[tot].to = v; edge[tot].next = head[u]; edge[tot].index = index; edge[tot].flag = false; head[u] = tot++; return ; } string str[1010]; int in[30]; int out[30]; int cnt; int ans[1010]; void dfs(int u) { for (int i = head[u]; i != -1; i = edge[i].next) { if (!edge[i].flag) { edge[i].flag = true; dfs(edge[i].to); ans[cnt++] = edge[i].index; } } return ; } int main() { // freopen("in.txt", "r", stdin); // freopen("out.txt", "w", stdout); int T, n; cin >> T; while (T--) { cin >> n; for (int i = 0; i < n; i++) { cin >> str[i]; } sort(str, str + n); //要输出字典序最小的解,先按照字典序排序 init(); memset(in, 0, sizeof(in)); memset(out, 0, sizeof(out)); int start = 100; for (int i = n - 1; i >= 0; i--) //字典序大的先加入 { int u = str[i][0] - 'a'; int v = str[i][str[i].length() - 1] - 'a'; addEdge(u, v, i); out[u]++; in[v]++; if (u < start) { start = u; } if (v < start) { start = v; } } int ccOne = 0; int ccTwo = 0; for (int i = 0; i < 26; i++) { if (out[i] - in[i] == 1) { ccOne++; start = i; //如果有一个出度比入度大1的点,就从这个点出发,否则从最小的点出发 } else if (out[i] - in[i] == -1) { ccTwo++; } else if (out[i] - in[i] != 0) { ccOne = 3; } } if (!((ccOne == 0 && ccTwo == 0) || (ccOne == 1 && ccTwo == 1))) { cout << "***" << endl; continue; } cnt = 0; dfs(start); if (cnt != n) //判断是否连通 { cout << "***" << endl; continue; } for (int i = cnt - 1; i >= 0; i--) { cout << str[ans[i]]; if (i > 0) { cout << '.'; } else { cout << endl; } } } return 0; }
混合图:
如果存在欧拉回路,一定存在欧拉路径,否则如果有且仅有两个点的(出度-入度)是奇数,那么给这两个点加边,判断是否存在欧拉回路,如果存在就一定存在欧拉路径。/* * POJ 1637 * 本题保证了连通,故不需要判断连通,否则要判断连通 */ const int MAXN = 210; const int MAXM = 20100; //最大流ISAP部分 const int INF = 0x3f3f3f3f; struct Edge { int to; int next; int cap; int flow; }edge[MAXM]; int tol; int head[MAXN]; int gap[MAXN]; int dep[MAXN]; int pre[MAXN]; int cur[MAXN]; void init() { tol = 0; memset(head, -1, sizeof(head)); return ; } void addEdge(int u, int v, int w, int rw = 0) { edge[tol].to = v; edge[tol].cap = w; edge[tol].next = head[u]; edge[tol].flow = 0; head[u] = tol++; edge[tol].to = u; edge[tol].cap = rw; edge[tol].next = head[v]; edge[tol].flow = 0; head[v] = tol++; return ; } int sap(int start, int end, int N) { memset(gap, 0, sizeof(gap)); memset(dep, 0, sizeof(dep)); memcpy(cur, head, sizeof(head)); int u = start; pre[u] = -1; gap[0] = N; int ans = 0; while (dep[start] < N) { if (u == end) { int MIN = INF; for (int i = pre[u]; i != -1; i = pre[edge[i ^ 1].to]) { if (MIN > edge[i].cap - edge[i].flow) { MIN = edge[i].cap - edge[i].flow; } } for (int i = pre[u]; i != -1; i = pre[edge[i ^ 1].to]) { edge[i].flow += MIN; edge[i ^ 1].flow -= MIN; } u = start; ans += MIN; continue; } bool flag = false; int v = 0; for (int i = cur[u]; i != -1; i = edge[i].next) { v = edge[i].to; if (edge[i].cap - edge[i].flow && dep[v] + 1 == dep[u]) { flag = true; cur[u] = pre[v] = i; break; } } if (flag) { u = v; continue; } int MIN = N; for (int i = head[u]; i != -1; i = edge[i].next) { if (edge[i].cap - edge[i].flow && dep[edge[i].to] < MIN) { MIN = dep[edge[i].to]; cur[u] = i; } } gap[dep[u]]--; if (!gap[dep[u]]) { return ans; } dep[u] = MIN + 1; gap[dep[u]]++; if (u != start) { u = edge[pre[u] ^ 1].to; } } return ans; } //the end of 最大流部分 int in[MAXN]; int out[MAXN]; int main() { //freopen("in.txt", "r", stdin); //freopen("out.txt", "w", stdout); int T; int n, m; cin >> T; while (T--) { cin >> n >> m; init(); int u, v, w; memset(in, 0, sizeof(in)); memset(out, 0, sizeof(out)); while (m--) { cin >> u >> v >> w; out[u]++; in[v]++; if (w == 0) { addEdge(u, v, 1); //双向 } } bool flag = true; for (int i = 1; i <= n; i++) { if (out[i] - in[i] > 0) { addEdge(0, i, (out[i] - in[i]) / 2); } else if (in[i] - out[i] > 0) { addEdge(i, n + 1, (in[i] - out[i]) / 2); } if ((out[i] - in[i]) & 1) { flag = false; } } if (!flag) { cout << "impossible" << endl; continue; } sap(0, n + 1, n + 2); for (int i = head[0]; i != -1; i = edge[i].next) { if (edge[i].cap > 0 && edge[i].cap > edge[i].flow) { flag = false; break; } } if (flag) { cout << "possible" << endl; } else { cout << "impossible" << endl; } } return 0; }
相关文章推荐
- 欧拉路径,欧拉回路,并查集
- 欧拉回路和欧拉路径的判断
- POJ-3360(欧拉路径和欧拉回路)
- 欧拉回路和欧拉路径
- fleury算法,欧拉回路,欧拉路径
- USACO - Riding the Fences (Fleury算法找欧拉路径/欧拉回路模板)
- 欧拉路径和欧拉回路的路径
- 欧拉回路以及欧拉路径
- ZOJ2016 POJ1386 HDU1116 Play on Words,欧拉路径及欧拉回路
- 【欧拉回路】【欧拉路径】【Fleury算法】CDOJ1634 记得小苹初见,两重心字罗衣
- fleury算法求欧拉路径(欧拉回路)模板
- 杭电ACM1116——Play on Words~~欧拉路径与欧拉回路
- 欧拉路径和欧拉回路的路径
- 欧拉路径和欧拉回路
- SGU 101 && POJ 1041 欧拉路径/欧拉回路
- 欧拉路径-欧拉回路
- 欧拉回路与欧拉路径
- POJ 2337 欧拉回路+欧拉路径+判断欧拉回路和路径
- USACO Section 3.3 Riding the Fences(欧拉路径和欧拉回路的路径)
- 欧拉回路(欧拉路径)