您的位置:首页 > 其它

【图论05】并查集 1002 小希的迷宫

2013-06-28 12:10 309 查看
算法思路;1.经典的并查集;2.连通且不存在回路条件:边数 + 1 = 顶点数

注意陷阱(测试数据本身设计不太合理):

0 0 Yes

1 1 0 0 Yes

//模板开始
#include <string>
#include <vector>
#include <algorithm>
#include <iostream>
#include <sstream>
#include <fstream>
#include <map>
#include <set>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include<iomanip>
#include<string.h>
#define SZ(x) (int(x.size()))
using namespace std;

int toInt(string s){
istringstream sin(s);
int t;
sin>>t;
return t;
}
template<class T> string toString(T x){
ostringstream sout;
sout<<x;
return sout.str();
}
typedef long long int64;
int64 toInt64(string s){
istringstream sin(s);
int64 t;
sin>>t;
return t;
}
template<class T> T gcd(T a, T b){
if(a<0)
return gcd(-a, b);
if(b<0)
return gcd(a, -b);
return (b == 0)? a : gcd(b, a % b);
}
//模板结束(通用部分)

#define ifs cin

int findset(int x, int pa[])
{
return pa[x] != x ? pa[x] = findset(pa[x], pa) : x;
}

//【图论05】并查集 1002 小希的迷宫
#define MAX_SIZE 100005
int next_node[MAX_SIZE];		//存储有向图的边
//int in[MAX_SIZE];		//存储节点的入度
//int out[MAX_SIZE];		//存储节点的出度
int flag[MAX_SIZE];		//标记节点是否存在

void init()		//初始化
{
for(int i = 0; i < MAX_SIZE; i++)
{
next_node[i] = i;
}
//memset(in, 0, sizeof(in));
//memset(out, 0, sizeof(out));
memset(flag, 0, sizeof(flag));
}

int findset(int a)		//找元素所在集合的代表元(因为用了路径压缩,路径压缩的主要目的是为了尽快的确定元素所在的集合)
{
while(next_node[a] != a)
{
a = next_node[a];
}
return a;
}

void union_nodes(int a, int b)		//集合合并
{
int a1 = findset(a);
int b1 = findset(b);
next_node[a1] = b1;
}

int main()
{
//ifstream ifs("shuju.txt", ios::in);
int m, n;

while(ifs>>m>>n && !(m == -1 && n == -1))
{
if(m == 0 && n == 0)
{
cout<<"Yes"<<endl;
continue;
}

int bianshu = 0;
init();
bianshu++;
union_nodes(m, n);
flag[m]++;
flag
++;

while(ifs>>m>>n && !(m == 0 && n == 0))		//输入数据,建立有向图,并合并相关集合
{
//int a = data[0] - 'a';
//int b = data[strlen(data) - 1] - 'a';
bianshu++;
union_nodes(m, n);
//out[a]++;
//in[b]++;
flag[m]++;
flag
++;
}

int count = 0;
for(int j = 0; j < MAX_SIZE; j++)		//计算有向图中连通分支的个数
{
if(next_node[j] == j && flag[j] != 0)
{
count++;
}
}

int jiedianshu = 0;
for(int j = 0; j < MAX_SIZE; j++)
{
if(flag[j] != 0)
{
jiedianshu++;
}
}

if(jiedianshu == 1)
{
cout<<"No"<<endl;
}

if(count == 1 && jiedianshu == bianshu + 1)
{
cout<<"Yes"<<endl;
}
else
{
cout<<"No"<<endl;
}
}

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: