description:看完題目,第一反應就是動態構造圖,然後每次輸入時進行連通性檢查。但是仔細一看,發現根本行不通。關係r具有對稱性和傳遞性。數對p q表示prq,p和q是0或自然數,p不等於q。
要求寫乙個程式將數對序列進行過濾,如果乙個數對可以通過前面數對的傳遞性得到,則將其濾去。例如:
輸入 輸出 連通性
3 4— 3 4
4 9— 4 9
8 0— 8 0
2 3— 2 3
5 6— 5 6
2 9— xx— 2-3-4-9
5 9— 5 9
7 3— 7 3
4 8— 4 8
5 6— xx— 5-6
0 2— xx— 0-8-4-3-2
6 1— 6 1
其中數對2 9和0 2可由之前數對的連通關係得到,故不做輸出。
input
輸入共有m行(0<=m<=1000000),每行乙個數對,數對的數字之間以1個空格分隔;數對的數字為0或n=100000以內的自然數。
output
輸出包含過濾之後的數對序列。每行輸出乙個數對,數對的數字之間以1個空格分隔。
sample input
3 4
4 9
8 0
2 3
5 6
2 9
5 9
7 3
4 8
5 6
0 2
6 1
sample output
3 4
4 9
8 0
2 3
5 6
5 9
7 3
4 8
6 1
如題目所示,節點數可能達到100000,構造乙個鄰接矩陣即使是bool型別也顯然超出記憶體限制,同時輸入資料可能達到1000000,每一次都進行bfs或dfs連通性檢測顯然會嚴重超時。
那麼只有走其他方法!
對於連通性檢測,如已知圖2-3-4-5,顯然2-3,2-4,2-5,3-4,3-5,4-5都是需要過濾的,不難發現:2是3,4,5的共同祖先,或者反過來,5是2,3,4的共同祖先。由此可以聯想到union-find,對結點進行分組。
我採用的第一種方法**如下:
# include
# define max 100001
using
namespace
std;
int data[max];
int main(void)
int point1, point2;
while(cin >> point1 >> point2) }}
}return
0;}
起初每個節點都屬於自己的組,我就暫且將它們各自的編號定義為它們的index。
當要查詢的兩個index在陣列中的值不同時,說明它們不屬於同乙個組,應當連通;否則,說明它們已經連通,需要過濾掉。
但有一點要注意,在連通時,應當把兩個組內所有成員都進行連通,但是我們又不知道哪些需要連通,只能把陣列遍歷一遍進行連通。
但是提交後發現**超時了!
接下來就是改進我的**了。
很顯然就是在連通時遍歷陣列耗時太長了,每一次連通都把100001個資料遍歷一次,實在是資源浪費,因為有時並沒有那麼多結點。
所以我改進了**,如下:
# include
# define max 100001
using
namespace
std;
int data[max];
int _max = 0;
int main(void)
int point1, point2;
while(cin >> point1 >> point2) }}
}return
0;}
我用_max變數儲存最大結點的值,這樣一來就不用將所有資料遍歷。
但是一提交,還是超時了!我估計測試資料裡可能一早就用到了乙個很大很大的結點。所以我改進後的**還是廢柴。
那麼,還是需要改進!!!
問題是:怎麼才能避免遍歷陣列?因為不知道哪些結點需要進行連通,才導致我們需要遍歷整個陣列。那麼我們怎樣才能找到這些結點而不需要遍歷陣列呢?
肯定要用到某種資料結構。鍊錶?集合?更深一層想,查詢最高效的就是樹了。
使用樹,我便能層層回溯,找到根結點,也就是它最終所屬的組,這樣我就可以避免遍歷了!
於是我進一步改進了我的**:
# include
# define max 100001
using
namespace
std;
int data[max];
int _max = 0;
int find(int num)
int main(void)
int point1, point2;
while(cin >> point1 >> point2)
}return
0;}
本想著這次肯定萬無一失能夠通過,還是太嫩了!依然超時!
為什麼會這樣?說明樹太深了,導致每次查詢根結點的時候耗費的資源太多了!我們必須在查詢的過程中將樹簡化。
於是我就修改了find函式,**如下:
# include
# define max 100001
using
namespace
std;
int data[max];
int _max = 0;
int find(int num)
int main(void)
int point1, point2;
while(cin >> point1 >> point2)
}return
0;}
然後,終於過了,哈哈哈~真是有趣的一道題! 連通性問題
1 伺服器可以ping通客戶端,說明伺服器和客戶端之間的鏈路是通的。客戶端不能ping通伺服器,很可能是防火牆的原因,包括伺服器本身自帶的防火牆和伺服器與交換機之間的cisco asa 5505防火牆。防火牆的訪問規則中清除禁止ping入之類的規則,或者清除拒絕接收icmp包的規則。2 ping不通...
動態連通性問題
首先定義演算法的api 方法作用 uf int n 初始化觸點及其他資料 int find int p 返回p所在連通分量的識別符號 int union int p,int q 在p和q之間新增一條線 int count 返回連通分量的數量 boolean connected int p,int q...
SOJ 連通性問題
description 關係r具有對稱性和傳遞性。數對p q表示prq,p和q是0或自然數,p不等於q。要求寫乙個程式將數對序列進行過濾,如果乙個數對可以通過前面數對的傳遞性得到,則將其濾去。例如 輸入 輸出 連通性 3 4 3 4 4 9 4 9 8 0 8 0 2 3 2 3 5 6 5 6 2...