Knots UVA - 1624

首先是初始化节点的状态信息,记录每个节点的左节点编号以及右节点标号,然后删除那些没有遮挡别的节点并且没有被别的节点遮挡的节点,然后开始下面的循环删除节点的过程,因为被遮挡以及遮挡其他节点的总数是2*P,每次首先找出没有被删除的节点,并且记录当前节点的右节点以及右节点的下一个右节点,然后判断这两个节点是否是在同一个平面上,然后判断这两个节点对应的另外一个面上的节点是否满足对应的相邻关系,如果满足就将这四个节点全部删除,如果上面的情况不满足,就判断这两个节点是否满足遮挡关系,如果满足,那么就将这两个节点全部删除。然后继续迭代判断。最后判断是否这2*P个节点全部被删除了,如果全部被删除了,那么输出“YES”否则输出“NO”,具体实现见如下代码:

#include<iostream>
#include<vector>
#include<string>
#include<set>
#include<stack>
#include<queue>
#include<map>
#include<algorithm>
#include<cmath>
#include<iomanip>
#include<cstring>
#include<sstream>
#include<cstdio>
#include<deque>
#include<functional>
#include<utility>
using namespace std;

int L, P;
typedef struct Node{
	int left, right, face;
}Node;
const int maxn = 1000000 + 10;
Node node[maxn];
int f[maxn],vis[maxn];

void del(int ind){
	vis[ind] = 1;
	node[node[ind].left].right = node[ind].right;
	node[node[ind].right].left = node[ind].left;
}

int main(){
	int T;
	cin >> T;
	for (int Case = 1; Case <= T; Case++){
		cin >> L >> P;
		for (int i = 0; i < L; i++){
			node[i].left = i - 1;
			node[i].right = i + 1;
			vis[i] = false;
		}
		memset(f, 0, sizeof(f));
		node[0].left = L - 1;
		node[L - 1].right = 0;
		for (int i = 0; i < P; i++){
			int A, B;
			cin >> A >> B;
			f[A] = 1;
			f[B] = -1;
			node[B].face = A;
			node[A].face = B;
		}
		for (int i = 0; i < L; i++){
			if (f[i] == 0){
				del(i);
			}
		}
		int id = 0;
		int amount = 2 * P;
		int x, y;
		while (amount){
			bool out = true;
			while (vis[id]) id++;
			for (int i = node[id].right; out&&i != id;i=node[i].right){
				x = i, y = node[i].right;
				if (f[x] == f[y] && (node[node[x].face].right == node[y].face
					|| node[node[y].face].right==node[x].face)){
					del(x);
					del(node[x].face);
					del(y);
					del(node[y].face);
					amount -= 4;
					out = false;
				}
				else if (node[x].face==y){
					del(x);
					del(y);
					amount -= 2;
					out = false;
				}
			}
			if (out) break;
		}
		cout << "Case #" << Case << ": " << (amount ? "NO\n" : "YES\n");
	}
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值