hdu1272_小希的迷宫
2011-09-27 20:32
267 查看
http://acm.hdu.edu.cn/showproblem.php?pid=1272
坑爹的题!!!
要判断图的连通性以及图是否有回路。。。要判断这两个东西都有好多方法。。
1、证明是否有回路
(1)判断 点数 = 边数 + 1 是否成立:
看到题目后好高兴,因为按照题意,如果图连通同时两点间只有一条路(不算回头路),那么这个图肯定是棵树,即 点数 = 边数 + 1 。
(证:n个独立的点为n个连通块,每加入一条边减少一个连通块,要形成一个连通块,至少要n-1条边;若图连通,则为树,在树上任意加上一条边都会形成回路,故无回路的连通图 边数 = 点数 - 1)
(2)利用顶点的度:每次把所有度为1或者0的点去掉,相关的边去掉,并把与边相关的另外的点的度都减1。不断重复这个步骤,直到图里没有度为1或0的点。
如果,此时图里没有点,则无回路;有点,则有回路。
2、剩下的就是判断图的连通性:
(1)通过一个点把所有连通的点加入,如果最后还有点没加入,则不连通。
(2)在上面利用点的度判断有否回路的过程中处理一下,就能顺便证明图是否连通的了。
(3)并查集:若所有点的根节点为同一节点,则图连通。
注意!只有一条边或者没有一个点的情况都算图连通的。
就这里坑死我了。。不断地debug,弄到最后,代码写得好恶心。。。求清爽代码。。。
代码1:
代码2:
坑爹的题!!!
要判断图的连通性以及图是否有回路。。。要判断这两个东西都有好多方法。。
1、证明是否有回路
(1)判断 点数 = 边数 + 1 是否成立:
看到题目后好高兴,因为按照题意,如果图连通同时两点间只有一条路(不算回头路),那么这个图肯定是棵树,即 点数 = 边数 + 1 。
(证:n个独立的点为n个连通块,每加入一条边减少一个连通块,要形成一个连通块,至少要n-1条边;若图连通,则为树,在树上任意加上一条边都会形成回路,故无回路的连通图 边数 = 点数 - 1)
(2)利用顶点的度:每次把所有度为1或者0的点去掉,相关的边去掉,并把与边相关的另外的点的度都减1。不断重复这个步骤,直到图里没有度为1或0的点。
如果,此时图里没有点,则无回路;有点,则有回路。
2、剩下的就是判断图的连通性:
(1)通过一个点把所有连通的点加入,如果最后还有点没加入,则不连通。
(2)在上面利用点的度判断有否回路的过程中处理一下,就能顺便证明图是否连通的了。
(3)并查集:若所有点的根节点为同一节点,则图连通。
注意!只有一条边或者没有一个点的情况都算图连通的。
就这里坑死我了。。不断地debug,弄到最后,代码写得好恶心。。。求清爽代码。。。
代码1:
#include <cstdio> #include <cstring> #include <vector> #include <queue> #include <algorithm> using namespace std; const int N = 100000 + 10; vector<int> adj ; int d ; int main() { // freopen("in.txt", "r", stdin); int x, y; while (scanf("%d%d", &x, &y) != EOF && (x != -1 || y != -1)) { //no point if (x == 0 && y == 0) { printf("Yes\n"); continue; } memset(d, 0, sizeof(d)); for (int i = 0; i < N; i++) adj[i].clear(); d[x]++, d[y]++; adj[x].push_back(y); adj[y].push_back(x); while (scanf("%d%d", &x, &y) != EOF && (x + y)) { d[x]++, d[y]++; adj[x].push_back(y); adj[y].push_back(x); } //判断是否无环and连通(利用无向图顶点的度) queue<int> q; for (int i = 1; i <= N; i++) if (d[i] == 1) { q.push(i); break; } while (!q.empty()) { int tmp = q.front(); d[tmp] = -1; q.pop(); if (adj[tmp].size() == 1) { int temp = adj[tmp][0]; for (int i = 0; i < adj[temp].size(); i++) { if (adj[temp][i] == tmp) adj[temp].erase(adj[temp].begin() + i); if (d[adj[temp][i]] <= 1) q.push(adj[temp][i]); } d[temp]--; if (d[temp] <= 1) q.push(temp); adj[tmp].clear(); } } int cnt = 0; for (int i = 1; i <= N; i++) if (d[i] > 0) cnt++; if (cnt == 0) printf("Yes\n"); else printf("No\n"); } }
代码2:
#include <cstdio> #include <cstring> #include <vector> #include <queue> using namespace std; const int N = 100000 + 10; bool used ; vector<int> adj ; int main() { // freopen("in.txt", "r", stdin); int x, y; while (scanf("%d%d", &x, &y) != EOF && (x != -1 || y != -1)) { //no point if (x == 0 && y == 0) { printf("Yes\n"); continue; } queue<int> q; q.push(x); int cnte = 0, cntp = 0; for (int i = 0; i < N; i++) adj[i].clear(); memset (used, 0, sizeof(used)); if (!used[x]) used[x] = 1, cntp++; if (!used[y]) used[y] = 1, cntp++; cnte++; adj[x].push_back(y); adj[y].push_back(x); while (scanf("%d%d", &x, &y) != EOF && (x != 0 || y != 0)) { if (!used[x]) used[x] = 1, cntp++; if (!used[y]) used[y] = 1, cntp++; cnte++; adj[x].push_back(y); adj[y].push_back(x); } //if the graph is connected memset(used, 0, sizeof(used)); used[q.front()] = true; int ans = 1; while (!q.empty()) { int tmp = q.front(); q.pop(); for (int i = 0; i < adj[tmp].size(); i++) if (!used[adj[tmp][i]]) { q.push(adj[tmp][i]); used[adj[tmp][i]] = true; ans++; } } //如果无回路,则顶点数等于边数+1 if (cnte == cntp - 1 && ans == cntp) printf("Yes\n"); else printf("No\n"); } }
相关文章推荐
- HDU - 1272 小希的迷宫(并查集)
- HDU 1272 小希的迷宫 并查集
- HDU-1272-小希的迷宫(并查集)
- HDU-1272:小希的迷宫
- 小希的迷宫 HDU - 1272
- hdu 1272 小希的迷宫
- HDU - 1272 - 小希的迷宫
- 小希的迷宫 hdu 1272(并查集)
- HDU 1272 小希的迷宫(并查集)
- HDU 1272--小希的迷宫【并查集,有值得注意的地方】
- hdu——1272——小希的迷宫(数)
- HDU 1272 小希的迷宫
- hdu1272_小希的迷宫
- HDU 1272 小希的迷宫
- hdu_1272_小希的迷宫
- hdu-1272 小希的迷宫
- HDU-1272 小希的迷宫(并查集)
- HDU 1272 小希的迷宫 (并查集)
- HDU 1272 小希的迷宫 (并查集)
- hdu-1272小希的迷宫