当前位置: 首页 > news >正文

C-Cleaning Pipes(判断两线段相交+二分图判定) 2015-2016 Northwestern European Regional Contest (NWERC 2015)

题意:

给定w个井口和p条管道,管道相交即代表有交点,现派出机器人进入若干管道进行清理交点,相交的管道之间最多允许存在一个机器人,问能否派出机器人将所有节点进行清理,且满足限制。

思路:

将管道抽象成点,如果管道之间存在交点则进行连边,所以问题就转化为了寻找一些点覆盖所有边且这些点之间不存在连边。从而问题就再次变成了判断连通图是否为二分图。

代码1(利用并差集判定二分图):

#include <bits/stdc++.h>
using namespace std;
const int maxn = 1005;
struct P {  
    int x, y;  
    P(int _x = 0, int _y = 0) : x(_x), y(_y) {}  
    bool operator == (P &b)  
    {  
        return x == b.x && y == b.y;  
    }  
} tmp[maxn], L[maxn], R[maxn];
//计算向量p1p2与向量p1p3的叉积,若p1p3在p1p2的逆时针方向,则返回>0,顺时针方向返回<0  
int mul(P p1, P p2, P p3)  
{  
    return (p2.x-p1.x) * (p3.y-p1.y) - (p3.x-p1.x) * (p2.y-p1.y);  
}  
bool intersect(P p1, P p2, P q1, P q2)  //利用线段1的两端点和线段2的两端点判断线段12是否相交
{  
	//快速排斥  
    if(max(p1.x,p2.x) < min(q1.x,q2.x)||  
       max(q1.x,q2.x) < min(p1.x,p2.x)||  
       max(p1.y,p2.y) < min(q1.y,q2.y)||  
       max(q1.y,q2.y) < min(p1.y,p2.y))  
    return 0;  
	//跨立试验  
    if(1ll*mul(p1,p2,q1)*mul(p1,p2,q2) <= 0 && 1ll*mul(q1,q2,p1)*mul(q1,q2,p2) <= 0)  
    return 1;  
    return 0;
}

int f[maxn*2];
int w, p;
int getf(int x){return x == f[x]? x: f[x] = getf(f[x]);}
void merge(int a, int b)
{
	int fa = getf(a), fb = getf(b);
	if(fa != fb) f[fb] = fa;
}
int main()
{
	//freopen("in.txt", "r", stdin);
	scanf("%d %d", &w, &p);
	for(int i = 1; i <= w; ++i)
	scanf("%d %d", &tmp[i].x, &tmp[i].y);
	for(int i = 1; i <= p; ++i)
	{
		int t;
		scanf("%d %d %d", &t, &R[i].x, &R[i].y);
		L[i] = tmp[t];
	}
	for(int i = 1; i <= 2*p; ++i) f[i] = i;
	for(int i = 1; i <= p; ++i)
	for(int j = i+1; j <= p; ++j)
	{
		if(L[i] == L[j]) continue;
		if(intersect(L[i], R[i], L[j], R[j]))
		{
			//如果有连边就将i,j+n归为一个集合,j,i+n归为一个集合 
			merge(i, j+p);
			merge(j, i+p);
		}
	}
	bool flag = true;
	for(int i = 1; i <= p; ++i)
	if(getf(i) == getf(i+p))
	//如果i和i+n属于同一个集合,则说明有奇环存在。
	{
		flag = false;
		break;
	}
	if(flag) puts("possible");
	else puts("impossible");
	return 0;
}


代码2(经典染色法判定二分图):

#include <bits/stdc++.h>
using namespace std;
const int maxn = 1005;
struct P {  
    int x, y;  
    P(int _x = 0, int _y = 0) : x(_x), y(_y) {}  
    bool operator == (P &b)  
    {  
        return x == b.x && y == b.y;  
    }  
} tmp[maxn], L[maxn], R[maxn];
//计算向量p1p2与向量p1p3的叉积,若p1p3在p1p2的逆时针方向,则返回>0,顺时针方向返回<0  
int mul(P p1, P p2, P p3)  
{  
    return (p2.x-p1.x) * (p3.y-p1.y) - (p3.x-p1.x) * (p2.y-p1.y);  
}  
bool intersect(P p1, P p2, P q1, P q2)  //利用线段1的两端点和线段2的两端点判断线段12是否相交
{  
	//快速排斥  
    if(max(p1.x,p2.x) < min(q1.x,q2.x)||  
       max(q1.x,q2.x) < min(p1.x,p2.x)||  
       max(p1.y,p2.y) < min(q1.y,q2.y)||  
       max(q1.y,q2.y) < min(p1.y,p2.y))  
    return 0;  
	//跨立试验  
    if(1ll*mul(p1,p2,q1)*mul(p1,p2,q2) <= 0 && 1ll*mul(q1,q2,p1)*mul(q1,q2,p2) <= 0)  
    return 1;  
    return 0;
}

int col[maxn];
int w, p;
vector<int> g[maxn];
bool dfs(int u, int key)
{
	col[u] = key;
	for(int i = 0; i < g[u].size(); ++i)
	{
		int v = g[u][i];
		if(col[v] == key) return false;
		if(col[v] != -1) continue;
		if(!dfs(v, key^1)) return false;
	}
	return true;
}
int main()
{
	//freopen("in.txt", "r", stdin);
	scanf("%d %d", &w, &p);
	for(int i = 1; i <= w; ++i)
	scanf("%d %d", &tmp[i].x, &tmp[i].y);
	for(int i = 1; i <= p; ++i)
	{
		int t;
		scanf("%d %d %d", &t, &R[i].x, &R[i].y);
		L[i] = tmp[t];
		g[i].clear();
	}
	for(int i = 1; i <= p; ++i)
	for(int j = i+1; j <= p; ++j)
	{
		if(L[i] == L[j]) continue;
		if(intersect(L[i], R[i], L[j], R[j]))
		{
			g[i].push_back(j);
			g[j].push_back(i);
		}
	}
	memset(col, -1, sizeof col);
	bool flag = true;
	for(int i = 1; i <= p; ++i)
	if(col[i] == -1 && !dfs(i, 0))
	{
		flag = false;
		break;
	}
	if(flag) puts("possible");
	else puts("impossible");
	return 0;
}


继续加油~

相关文章:

  • eclipse the user operation is waiting for building workspace to complete
  • 2-SAT 题目整理
  • 64位windows2003 未在本地计算机上注册 microsoft.jet.oledb.4.0 提供程序
  • HDU-5950 Recursive sequence(矩阵乘法)
  • “互联网+”引发IT人才招工荒-新华网安徽频道
  • Java从文件读入以及读出至文件
  • HDU-5963 朋友(树上博弈)
  • HDU 6005 Pandaland(无向图最小环)
  • Cura源码在Ubuntu15.04上编译脚本(成功)
  • SPOJ - CHICAGO 106 miles to Chicago(乘积最短路)
  • HTML5之FileReader的使用
  • LeetCode 202 Happy Number(floyd判圈算法(龟兔赛跑算法))
  • css3 中text-align:justify
  • HDU-1503 Advanced Fruits(LCS)
  • LightOJ-1253 Misere Nim(Nim求解不正常的博弈)
  • [Vue CLI 3] 配置解析之 css.extract
  • android 一些 utils
  • ES6系统学习----从Apollo Client看解构赋值
  • HTTP中GET与POST的区别 99%的错误认识
  • JavaScript HTML DOM
  • JavaScript的使用你知道几种?(上)
  • Netty源码解析1-Buffer
  • Solarized Scheme
  • Storybook 5.0正式发布:有史以来变化最大的版本\n
  • Work@Alibaba 阿里巴巴的企业应用构建之路
  • 从0到1:PostCSS 插件开发最佳实践
  • 多线程 start 和 run 方法到底有什么区别?
  • 构造函数(constructor)与原型链(prototype)关系
  • 汉诺塔算法
  • 微服务核心架构梳理
  • 异常机制详解
  • 用jQuery怎么做到前后端分离
  • const的用法,特别是用在函数前面与后面的区别
  • ​​​​​​​​​​​​​​Γ函数
  • ​【已解决】npm install​卡主不动的情况
  • "无招胜有招"nbsp;史上最全的互…
  • (论文阅读40-45)图像描述1
  • (每日持续更新)jdk api之StringBufferInputStream基础、应用、实战
  • (太强大了) - Linux 性能监控、测试、优化工具
  • (学习日记)2024.02.29:UCOSIII第二节
  • (转)关于pipe()的详细解析
  • (轉貼) 2008 Altera 亞洲創新大賽 台灣學生成果傲視全球 [照片花絮] (SOC) (News)
  • *(长期更新)软考网络工程师学习笔记——Section 22 无线局域网
  • .NET 常见的偏门问题
  • .net 发送邮件
  • .NET高级面试指南专题十一【 设计模式介绍,为什么要用设计模式】
  • .net下简单快捷的数值高低位切换
  • [ 网络基础篇 ] MAP 迈普交换机常用命令详解
  • [2023年]-hadoop面试真题(一)
  • [Android View] 可绘制形状 (Shape Xml)
  • [C#] 如何调用Python脚本程序
  • [C#]OpenCvSharp使用帧差法或者三帧差法检测移动物体
  • [C++] cout、wcout无法正常输出中文字符问题的深入调查(1):各种编译器测试
  • [CDOJ 838]母仪天下 【线段树手速练习 15分钟内敲完算合格】
  • [ESP32] 编码旋钮驱动