首先,我们可以舍弃掉第三维,那样的话每种金属就是平面上的点了。
对于任意两个点x,y,假如用户点都不在右边,则从x至y连条长度为1的有向边。
然后Flody求个最小环。
#include <cstdlib>
#include <cstdio>
#include <iostream>
#include <cstring>
#include <cmath>
#include <cctype>
#include <algorithm>
#define rep(i, l, r) for(int i=l; i<=r; i++)
#define pi acos(-1)
#define eps 1e-8
#define inf 0x3fffffff
#define maxn 509
typedef long long ll;
using namespace std;
inline int read()
{
int x=0, f=1; char ch=getchar();
while (!isdigit(ch)) {if (ch=='-') f=-1; ch=getchar();}
while (isdigit(ch)) x=x*10+ch-'0', ch=getchar();
return x*f;
}
struct P{double x, y;} k[maxn], q[maxn];
P operator - (P a, P b){return (P){a.x-b.x, a.y-b.y};}
double operator * (P a, P b){return a.x*b.y-a.y*b.x;}
int n, m, d[maxn][maxn];
inline bool spj()
{
rep(i, 2, n) if (abs(k[i].x-k[1].x)>eps || abs(k[i].y-k[1].y)>eps) return 0;
rep(i, 1, m) if (abs(q[i].x-k[1].x)>eps || abs(q[i].y-k[1].y)>eps) return 0;
puts("1"); return 1;
}
inline bool cos(P a, P b)
{
if (a.x>b.x) swap(a, b);
rep(i, 1, m) if (q[i].x<a.x || b.x<q[i].x) return 0;
if (a.y>b.y) swap(a, b);
rep(i, 1, m) if (q[i].y<a.y || b.y<q[i].y) return 0;
return 1;
}
inline int jud(P a, P b)
{
int c1=0, c2=0;
rep(i, 1, m)
{
double t=(b-a)*(q[i]-a);
if (t>eps) c1++;
if (t<-eps) c2++;
if (c1*c2) return 0;
}
if (!c1&&!c2&&cos(a, b)) {puts("2"); return -1;}
if (!c2) return 1;
if (!c1) return 2;
return 3;
}
int main()
{
n=read(), m=read(); double tmp;
rep(i, 1, n) scanf("%lf%lf%lf", &k[i].x, &k[i].y, &tmp);
rep(i, 1, m) scanf("%lf%lf%lf", &q[i].x, &q[i].y, &tmp);
if (spj()) return 0;
rep(i, 1, n) rep(j, 1, n) d[i][j]=inf;
rep(i, 1, n) rep(j, i+1, n)
{
int flag=jud(k[i], k[j]);
if (flag==-1) return 0;
if (flag==1) d[i][j]=1;
if (flag==2) d[j][i]=1;
if (flag==3) d[i][j]=d[j][i]=1;
}
rep(i, 1, n) rep(j, 1, n) rep(o, 1, n) if (d[i][j]>d[i][o]+d[o][j]) d[i][j]=d[i][o]+d[o][j];
int ans=inf; rep(i, 1, n) if (d[i][i]<ans) ans=d[i][i];
if (ans<3 || ans==inf) ans=-1;
printf("%d
", ans);
return 0;
}