并查集的简单应用。zoj数据太弱,程序中判断是否找到路径的条件 /* aaaaaa */是错误的,比如对于下面这个例子:
1
1 5
2 1
4 5
1 3
3 4
它的输出是找不到连通路径,但事实上是能找到的。但是这个错误的程序能通过oj测评。
#include<iostream>
#include<fstream>
#include<cstdlib>
#include<string>
#include<map>
#include<cmath>
using namespace std;
map<int,int> uset; /*并查集*/
int start,end;
int n;
/*查找并压缩路径*/
bool uset_find(int x){
if(uset.find(x)==uset.end()) return false;
int p = x, y;
while(uset[p]!=p) p = uset[p];
while((y=uset[x])!=p){ uset[x] = p; x = y;} /*压缩路径*/
return true;
}
void uset_union(int x,int y){
uset[uset[y]] = uset[x];
}
int main(){
freopen("input.txt","rb",stdin);
scanf("%d\n",&n);
int test_case = 0;
while(n!=0){
test_case++;
bool haveFound = false; /*判断是否已经找到从start通向end的路径*/
string s(n,' ');
for(int i=0;i<n;i++) scanf("%c ",&s[i]);
start = atoi(s.c_str());
for(int i=0;i<n-1;i++) scanf("%c ",&s[i]);
scanf("%c\n",&s[n-1]);
end = atoi(s.c_str());
/*path*/
int x,y;
while(scanf("%c",&s[0])==1){
if(s[0]=='-'){ scanf("%d\n",&n); break; } /*跳过-1;*/
scanf(" ");
for(int i=1;i<n;i++) scanf("%c ",&s[i]);
x = atoi(s.c_str());
for(int i=0;i<n-1;i++) scanf("%c ",&s[i]);
scanf("%c\n",&s[n-1]);
y = atoi(s.c_str());
if(haveFound==false){ /*如果已经找到连通路径,则没有必要进行下述操作*/
if(!uset_find(x) && !uset_find(y)){ uset[x] = x; uset[y] = x;} /*x,y都是第一次出现*/
else{
if(uset_find(x) && !uset_find(y)){
uset[y] = uset[x];
}
else if(!uset_find(x) && uset_find(y)){
uset[x] = uset[y];
}
else{
uset_union(x,y); /*合并*/
}
}
}
/* aaaaaa
if(!haveFound && uset.find(start)!=uset.end()&&uset.find(end)!=uset.end() && uset[start]==uset[end]){
printf("Maze #%d can be travelled\n",test_case); haveFound = true;
}
*/
if(!haveFound && uset_find(start) && uset_find(end) && uset[start]==uset[end]){
printf("Maze #%d can be travelled\n",test_case); haveFound = true;
}
}
if(!haveFound) printf("Maze #%d cannot be travelled\n",test_case);
uset.clear(); /*别忘了清空并查集*/
scanf("%d\n",&n);
}
return 0;
}