您的位置:首页 > 其它

POJ 1182 食物链【关系并查集】

2017-11-10 11:14 387 查看
Problem:

A吃B,B吃C,C吃A,给了一系列的关系,判断两个东西的关系是否和已给的关系冲突。

Solution:

将关系当做一个权加入并查集当中,相关关系在一个树上。

具体解法这篇链接讲的很清楚,但是它的代码我觉得还有很大的改进空间,比如还可以提炼出举一反三的模板,代码可读性还可以增加,主函数当中的逻辑冗余,所以我在看懂了这篇博客之后自己又进行了修改和总结。

参考链接:http://blog.csdn.net/niushuai666/article/details/6981689

note:

1. 一定要记得并查集的初始化。

#include<cstdio>
#include<iostream>
#include<sstream>
#include<cstdlib>
#include<cmath>
#include<cctype>
#include<string>
#include<cstring>
#include<algorithm>
#include<stack>
#include<queue>
#include<set>
#include<map>
#include<ctime>
#include<vector>
#include<fstream>
#include<list>
#include<iomanip>

using namespace std;

typedef long long ll;
typedef unsigned long long ull;
#define ms(s) memset(s,0,sizeof(s))

const double PI = 3.141592653589;
const int INF = 0x3fffffff;

template <typename Type>
class DisjointSet {
struct node {
int parent_;
Type relation_; //parent -> this
node() {
relation_ = 0;
}
};

vector<node> nodes;
vector<int> parents;

public:
bool is_relation_;

DisjointSet(int number_nodes, bool is_relation = false) {
is_relation_ = is_relation;

if(is_relation_) {
nodes.resize(number_nodes+1);
for(int i = 0; i <= number_nodes; ++i)
nodes[i].parent_ = i;
} else {
parents.resize(number_nodes+1);
for(int i = 0; i <= number_nodes; ++i)
parents[i] = i;
}
}

int find(int x) {
if(is_relation_) {
if(nodes[x].parent_ != x) {
int xparent = nodes[x].parent_; // x's old parent
nodes[x].parent_ = find(nodes[x].parent_);
nodes[x].relation_ = nodes[x].relation_ + nodes[xparent].relation_;
}
return nodes[x].parent_;
} else {
if(parents[x] != x)
parents[x] = find(parents[x]);
return parents[x];
}
}

Type get_relation(int x) {
return nodes[x].relation_;
}

void merge(int x, int y) {
parents[find(y)] = find(x);
}

void merge(int x, int y, Type relation) {
// relation: x->y
int yparent = find(y);
nodes[yparent].parent_ = find(x);
nodes[yparent].relation_ = nodes[x].relation_ + relation - nodes[y].relation_;
}
};

int main() {
//    freopen("/Users/really/Documents/code/input","r",stdin);

int n, k;

scanf("%d%d", &n, &k);

DisjointSet<int> ds(n, true);

int d, x, y, ans = 0;
for(int i = 0; i < k; i++) {
scanf("%d%d%d", &d, &x, &y);

if(x > n || y > n)
ans++;
else if(d == 2 && x == y)
ans++;
else if(ds.find(x) == ds.find(y)) {
if(d-1 != ((ds.get_relation(y)-ds.get_relation(x))%3 + 3)%3)
ans++;
}
else {
ds.merge(x, y, d-1);
}
}

printf("%d\n", ans);

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