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:
#include <cstdio>
#include <cstring>
#include <vector>
#include <queue>
#include <algorithm>
using namespace std;
const int N = 100000 + 10;
vector<int> adj[N];
int d[N];
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[N];
vector<int> adj[N];
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");
}
}