【NWERC2015】【BZOJ4427】Cleaning Pipes清理管道

Description

Linköping has a quite complex water transport system. Around Linköping there are several wells from which water is drawn. The water is then transported to other locations using pipes. Each pipe is a straight canal from one of the wells to some location in the city.
All the pipes are at the same depth under ground. Therefore, whenever two pipes cross, they form an intersection. Luckily the pipe system was constructed in such a way that exactly two pipes meet at each such intersection. The wells do not count as intersections. Any number of pipes (including zero or more than two) may originate at each well.
The intersections pose a problem, since dirt (a mixture of lime and other “remains”) tends to get stuck there. This dirt causes the pipes to degrade and collapse, leading to the formation of large sink holes. Such sink holes have a mesmerising effect on the students in Linköping, causing them to neglect their studies and remain uneducated, which in the long run will lead to a collapse of not just the pipe system but of the very fabric of society. Therefore it is imperative that the pipes are regularly cleaned. The Nordic Water Extraction and Redistribution Company (NWERC) – which is in charge of Linköping’s waterpipes – has an ample fleet of robots to perform this task. A robot can be inserted into a pipe at the well where the pipe begins. The robot then goes through the pipe all the way to its end and cleans all intersections along the way. After reaching the end, the robot turns around and returns back to the well where it started. In order to prevent robot collisions, government regulations stipulate that whenever two pipes intersect, at most one of them may contain a robot.
Since the whole water system has to be shut down while it is being cleaned (another government regulation), the NWERC would like to do the cleaning quickly, by using a single batch of cleaning robots, all started at the same time.
Your task is to verify whether this can be done – i.e., whether we can simultaneously insert robots into a subset of the pipes in such a way that the robots will clean all intersections and there will be no risk of two robots colliding.
Linköping有一个相当复杂的水资源运输系统。在Linköping周围的出水点有一些水井。这些水通过管道输送到其它地点。每条管道是从某一个水井到城市的某个位置的直线管道。
所有管道在地下的深度相同。因此,无论何时,两个管道相交时,它们会形成交点。幸运的是,管道系统正好是以满足两个管道有交点的方式建造。井不计入交点。任何数量的管道(包括零个与超过两个)都可以来源于每一个水井。
这些交点导致了一个问题,因为污垢(石灰和其它东西的混合物)往往会卡住交点,导致管道崩溃和坍塌,导致大型水槽孔的形成。这样的水槽孔对Linköping的学生有吸引的效果,使他们荒废学业,不受教育,这从长远来看将不只是导致管道系统的崩溃,还有社会的结构。因此,当务之急是管道定期清理。北欧提水再分配公司(NWERC) -负责Linköping的水管的 – 拥有充足的机器人车队才可以完成此任务。一个机器人可以在一条管道的开始位置被插入。然后,机器人通过管道一直到结束,并清除沿途所有交点。到达终点后,机器人转身并返回它开始的井。为了防止机器人互相碰撞,政府法规规定每当两个管相交,它们中的至多一个可以包含一个机器人。
由于整个水系统在被清洁时必须关闭(另一政府法规),则NWERC想迅速完成清洗,使用一批次清洁机器人,都必须在同一时间开始。
你的任务是验证是否可以做到这一点 - 即,是否能够把机器人同时插入管道中的一些,在不会有两个机器人相撞的危险下清洁所有交点。
Input

The input consists of:
• one line with two integers ww (1≤w≤10001≤w≤1000), the number of wells, and pp (1≤p≤10001≤p≤1000), the number of pipes;
• ww lines, the iith of which contains two integers xixi and yiyi (−10000≤x,y≤10000−10000≤x,y≤10000), the position of well number ii (the wells are numbered from 11 to ww);
• pp lines each with three integers ss (1≤s≤w1≤s≤w), the well at which the pipe starts, and xx and yy (−10000≤x,y≤10000−10000≤x,y≤10000), the position at which the pipe ends.
Each pipe will contain exactly one well, the one at which it starts. Any point shared by more than two pipes will be a well. Any two pipes share at most one common point. The common point of two pipes may be the endpoint of one or both of them. All pipes have positive length.
输入包括:
第一行两个整数w(1<=w<=1000)和p(1<=p<=1000),分别表示井的数量和管道的数量。
接下来w行,每行两个整数xi和yi(-10000<=x,y<=10000),表示i号井的位置(井从1到w编号)。
接下来p行,每行3个整数s(1<=s<=w)表示管道从s号井开始,x和y(-10000<=x,y<=10000)表示管道在位置为x,y的点结束。
每条管道都有一个井,就是它开始的那个。被两个或多个管道共享的点是一口井。任两条管道至多会有一个交点。两条管道的公共点可以是他们其中之一或两者的端点。所有管道的长度为正数。
Output

If it is possible to clean all intersections as described above, output “possible”. Otherwise, output “impossible”.
如果在上述情况下可以清理所有交点,输出“possible”,否则输出“impossible”。
Sample Input

Sample input 1

3 3

0 0

0 2

2 0

1 2 3

2 2 2

3 0 3

Sample input 2

2 3

0 0

0 10

1 5 15

1 2 15

2 10 10
Sample Output

Sample output 1

impossible

Sample output 2

possible

HINT

Source

枚举题意好题.
边相交则在新图两点连边,然后二分图判定.
坑非常多(主要在判相交处)
交点是井会XXX,交点是端点会XXX.
终于明白这道思博题为什么A的人那么少,因为练习的是枚举题意.
这里写图片描述

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<queue>
#define MAXN 1010
#define GET (ch>='0'&&ch<='9')
using namespace std;
int n,m,top;
int col[MAXN];
struct point
{
    int x,y;
    point(int _x=0,int _y=0):
        x(_x),y(_y){}
}s[MAXN];
typedef point Vector;
struct line
{
    point a,b;
    line (point _a=point(0,0),point _b=point(0,0)):
        a(_a),b(_b){}
}q[MAXN];
struct edge {   int to;edge *next;  }e[MAXN*MAXN],*prev[MAXN];
inline void insert(int u,int v) {   e[++top].to=v;e[top].next=prev[u];prev[u]=&e[top];  }
Vector operator +(Vector A,Vector B)    {   return Vector(A.x+B.x,A.y+B.y); }
Vector operator -(Vector A,Vector B)    {   return Vector(A.x-B.x,A.y-B.y); }
double operator *(Vector A,Vector B)    {   return A.x*B.y-A.y*B.x; }
bool operator !=(Vector A,Vector B) {   return A.x!=B.x||A.y!=B.y;  }
bool operator ==(Vector A,Vector B) {   return A.x==B.x&&A.y==B.y;  }
inline int sqr(int x)   {   return x*x; }
inline int unit(int x)  {   return !x?0:(x>0?1:-1); }
inline bool inter(Vector a,Vector b,Vector c,Vector d)  {   return (unit((b-a)*(c-a))*unit((b-a)*(d-a))<0)&&(unit((d-c)*(a-c))*unit((d-c)*(b-c))<0);    }
inline void in(int &x)
{
    char ch=getchar();x=0;int flag=1;
    while (!GET)    flag=ch=='-'?-1:1,ch=getchar();
    while (GET) x=x*10+ch-'0',ch=getchar();x*=flag;
}
int main()
{
    in(n);in(m);int w,x,y;
    for (int i=1;i<=n;i++)  in(x),in(y),s[i]=point(x,y);
    for (int i=1;i<=m;i++)  in(w),in(x),in(y),q[i].b=point(x,y),q[i].a=s[w];
    for (int i=1;i<=m;i++)  for (int j=i+1;j<=m;j++)
        if ((inter(q[i].a,q[i].b,q[j].a,q[j].b)||q[i].b==q[j].b)&&(q[i].a!=q[j].b&&q[i].b!=q[j].a&&q[i].a!=q[j].a)) insert(i,j),insert(j,i);
    queue<int> q;
    for (int i=1;i<=m;i++)
    {
        if (col[i]) continue;
        q.push(i);col[i]=1;
        while (!q.empty())
        {
            int x=q.front();q.pop();
            for (edge *i=prev[x];i;i=i->next)
                if (col[i->to]==col[x]) return puts("impossible"),0;
                else    if (!col[i->to])    col[i->to]=col[x]==1?2:1,q.push(i->to);
        }
    }
    puts("possible");
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值