NOI2015 day1 prog 程序自动分析(并查集)

来源:互联网 发布:scala 用 java的类 编辑:程序博客网 时间:2024/04/30 04:37
程序自动分析
【问题描述】
在实现 程序自动分析 的过程 中,常 需要判定一些 约束 条件是否能被 同时 满 足。
考虑 一个约束满足问题 的简化版本: 假设 x1,x2,x3,⋯ 代表 程序中出现的变 量,给定 n 个形如 xi=xj或 xi≠xj 的变量相等 变量相等 变量相等 变量相等 /不等 的约束 条件 ,请判定 是否 可以 分别 为每一个变量 赋予恰当的 值, 使得上述所有 约束 条件同时被 满足 。例如 , 一个问题 一个问题 中的约束 条件 为:x1=x2,x2=x3,x3=x4,x1≠x4 ,这些约束条件 ,这些约束条件 ,这些约束条件 显 然是不可 能同时被 满足的 ,因此 这个问题 应判定为不可被满足 。

现在给出一些约束满足 问题,请分别 对它们进行 判定。

【输入格式】
输入文件的第 1 行包含 1 个正整数 t ,表示 ,表示 需要判定的问题个数 。注意这些 注意这些 注意这些 问题 之间 是相互独立的。 是相互独立的。 是相互独立的。
对于每个 问题 ,包含 若干行 :
第 1 行包含 1 个正整数n ,表示 该问题中需要被满足的 约束 条件 个数 。
接下来 n行,每包括 行,每包括 3 个整数 i,j,e ,描述 1 个相等 /不等的 约束 条件 ,相 邻整数之间用单个 整数之间用单个 整数之间用单个 整数之间用单个 空格隔开。 空格隔开。 空格隔开。 若 e=1 ,则 该约束条件为 该约束条件为 该约束条件为 该约束条件为 xi= xj ;若 e=0 , 则该约束条件为 xi ≠ xj

【输出格式】
输出 文件包括 t 行。
输出 文件的 第 k行输出 一个字符串“ 一个字符串“ YES ”或者 “NO ”(不包含引号,字母 (不包含引号,字母 (不包含引号,字母 (不包含引号,字母 (不包含引号,字母 (不包含引号,字母 (不包含引号,字母 全部大写) 全部大写) 全部大写) ,“YES ”表示 输入中的第 k 个问题 判定为 可以 被满足, “NO ”表示不 可被满足。



哦很久没写blog了。。本沙茶这次NOI网赛唯一全A的一题 T_T 。。

这题一眼并查集,因为等号具有传递性,将所有用等号连接的集合合并一下就行了。但是要注意只能开一个并查集来维护所有等量关系,千万不要在开一个维护不等关系!(a!=b, b!=c, 合并后会推出a!=c,然而并不一定这样)先将所有等量关系维护后,再弄依次判断不等关系是否和集合冲突即可。


#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>using namespace std;const int MAXN = 1000010;int N, T;int fa[MAXN*2];void get(int &r) { //n很大,数据组数也多,最好加读入外挂    char c; r=0;    do c=getchar(); while (c<'0'||c>'9');    do{r=r*10+c-'0';c=getchar();}while (c>='0'&&c<='9');}int data[MAXN][2]; //记录输入数据以离散化int b[MAXN*2]; //记录是等号还是不等号int arr[MAXN * 2], cnt, len;int bifind(int x) {  //二分查找(lower_bound比手写的慢三倍。。)int l = 1, r = len, mid = (l + r) >> 1;while (l < r) {if (arr[mid] == x) return mid;if (arr[mid] < x) l = mid + 1;else r = mid - 1;mid = (l + r) >> 1;}return mid;}struct Stack { //无聊的手写栈int sta[MAXN*2], tp;bool empty() {return tp==0;}int top() {return sta[tp];}void push(int x) {sta[++tp]=x;}void pop() {--tp;}void clear() {tp=0;}} z;void init() {for (int i = 1; i<=len; ++i) //这里是len不是n。。n是关系的个数,len才是变量个数fa[i] = i;}int root(int x) { //用手写栈实现的路径压缩防止递归爆栈。然而由于路径压缩的存在并不需要。。while (fa[x] != x && x != -1) z.push(x), x = fa[x];while (!z.empty()) fa[z.top()] = x, z.pop();return x;}bool solve() {init();int i, t1, t2;for (i = 1; i<=N; ++i) //先将所有相等关系合并成集合if (b[i] == 1) {t1 = bifind(data[i][0]);t2 = bifind(data[i][1]);if (root(t1) != root(t2))fa[root(t1)] = root(t2);}for (i = 1; i<=N; ++i)if (b[i] == 0) {t1 = bifind(data[i][0]);t2 = bifind(data[i][1]);if (root(t1) == root(t2)) //检查是否冲突return 0;}return 1;}int main(){//freopen("prog.in", "r", stdin);//freopen("prog.out", "w", stdout);int i;get(T);while (T--) {get(N);cnt = 0;for (i = 1; i<=N; ++i) {get(data[i][0]); get(data[i][1]);get(b[i]);arr[++cnt] = data[i][0];arr[++cnt] = data[i][1];}sort(arr+1, arr+cnt+1);len = unique(arr+1, arr+cnt+1) - (arr+1); //len保存离散化后变量个数(重复出现不计)if (solve()) puts("YES");else puts("NO");}return 0;}




0 0
原创粉丝点击