您的位置:首页 > 其它

HDU 1272 小希的迷宫 (水题)

2015-06-29 23:45 309 查看
题意:

  其实就是让你判断一个图是否为树,要求不能有孤立的点(没有这中情况),且只能有1个连通图,且边数+1=点数,且每个点都有边(不可能只有1个点出现)。

思路:

  有可能出现连续的4个0,也就是有测试例子是完全没有点的,也没有边,要打印Yes!记录下所有点(去重),记录下每个点的度数,如果有n个点,n-1条边,且每点都是有边连着的,再判断其只有一个连通图就行了。因为只有n-1条边,所以当只有一个连通图时,必不会有环的产生。

判断是否只有一个连通图的方法:

(1)BFS(可用)

(2)DFS(有10万点,可能爆栈)

(3)并查集(可用)

(4)prim、kruscal生成一个树,所有点和所有边都要用上。

(5)Dijkstra、Bellman-Ford 求单点到其他点的路径长,如果有两点的路径为无穷则证明有点不可达。

#include <bits/stdc++.h>
using namespace std;
const int N=100005, mod=0x7f7f7f7f;
unordered_map<int,int> mapp;//将点编号映射到从1开始的连续的编号
int pre
;
int find(int a) //查
{
int tmp=a;
while(pre[tmp]!=tmp)    tmp=pre[tmp]; //找到a的祖先
pre[a]=tmp; //改其祖先
int p;
while(a!=tmp)   //从a到tmp所经过的点,改其全部祖先
{
p=pre[a];
pre[a]=tmp;
a=p;
}
return tmp;
}

void joint(int a,int b) //并
{
a=find(a);
b=find(b);
if(a!=b)    pre[a]=b;
}

void init() //初始化pre,不知道点个数,所以只能这样了
{
for(int i=1; i<=N; i++)    pre[i]=i;
}

int istree(int n)    //每个房间都是连着的
{
for(int i=1; i<=n; i++)    find(i); //防止漏网之鱼
for(int i=1; i<n; i++)     if(pre[i]!=pre[i+1]) return 0;   //不是同个领导的
return 1;
}

int main()
{
freopen("e://input.txt", "r", stdin);
int n, a, b;
while(1)
{
memset(pre,0,sizeof(pre));
mapp.clear();
init();         //初始化pre[]祖先列表
int cnt=0, j=0;

while(scanf("%d%d",&a,&b),a>0&&b>0)
{
//cout<<"123"<<endl;
if(!mapp[a])    mapp[a]=++j;    //重新编号
if(!mapp[b])    mapp[b]=++j;

joint(mapp[a], mapp[b]);
cnt++;         //边数
}
if(a==-1 || b==-1)    break;

if(!cnt)    printf("Yes\n");    //坑
else if(cnt+1!=j)    printf("No\n");//边多了肯定不行
else
{
if(istree(j))    printf("Yes\n");
else    printf("No\n");
}
}
return 0;
}


AC代码(并查集实现)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: