P1394 山上的国度
这道题我第一眼看上去好像可以bfs,就是先找出最高的点,再由高的点向低的点连一条有向边,然后再bfs一遍看看有没有断点,(我这个想法不知道是否正确),然后写完后我发现了一个严酷的问题,我好像不会写bfs(果然我太弱了),于是写炸了。
于是我换了一条路——用并查集,因为有个条件,水从高向低流,于是我想,可不可以这样做,通过并查集对每一组点进行操作,使更高的点作为更低的点的父亲,就是这样的操作:
大体就是这个想法,具体实现在代码上,(求管理员过)
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<algorithm>
#include<ctime>
#include<queue>
using namespace std;
const int maxa = 350;
int n,m,fa[maxa],ans=0,h[maxa],u[maxa],v[maxa];
inline int find(int x){
if(x==fa[x])return x;
else return fa[x]=find(fa[x]);
}
void merge(int x,int y){//合并
int rx=find(x);//一定要找父亲
int ry=find(y);
fa[ry]=rx;
}
bool check = true;//算是一个预处理,假设全联通。
int main(){
//int mark,am=0;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;++i){
scanf("%d",&h[i]);
// am=max(h[i],am);//失败bfs痕迹
//mark=i;
}
for(int i=1;i<=n;++i)fa[i]=i;//初始化“我是我的父亲”
for(int i=1;i<=m;++i){
scanf("%d%d",&u[i],&v[i]);
if(h[u[i]]>h[v[i]]){//合并判断
merge(u[i],v[i]);
}
if(h[u[i]]<h[v[i]]){
merge(v[i],u[i]);
}
}
for(int i=2;i<=n;++i){
if(find(i-1)!=find(i)){//如果有没在集合中的点,直接 沙特down
check=false;
}
}
if(!check){
printf("Non");
}
else{
printf("Oui, j'ai trouve la solution.\n");
printf("%d",find(1));
}
return 0;
}
请记住,我太弱了