Problem:
Problem G: Nurie
紙の上に円が
n
個書かれている. うさぎは
k
色の絵の具を持っていて, 次のルールに従って紙に色を塗っていく.
各領域をある1 色の絵の具で塗るか, 何も塗らない. ここで「領域」とは, 円弧の集合で囲まれた面積有限の部分を指す.
隣り合っている2 つの領域を同じ色の絵の具で塗ることはできない. ここで「隣り合っている」とは,境界の一部を共有する円弧があることを指す. 共有点が有限個である2 つの領域は, 隣り合っているとはみなされない.
隣り合っている2 つの領域の両方を塗らないままにすることは許される.
うさぎはできるだけ多くの領域を絵の具で塗りたい. 塗れる領域の個数の最大値を求めよ.
Input
1 行目:
n k
(1 ≤
n
≤ 20, 1 ≤
k
≤ 1 000 000 000)
2-(
n
+ 1) 行目:
x
i
y
i
r
i
, (−1 000 ≤
x
i
,
y
i
≤ 1 000, 1 ≤
r
i
≤ 1 000) (整数)
どの2 つの円も一致しない.
いずれか2 円の交点として得られる点集合は, 距離が10
−3
以下の異なる2 点を含まない.
Output
絵の具で塗れる領域の個数の最大値を一行に出力せよ.
Sample Input 1
2 1
10 0 10
20 0 10
Sample Output 1
2

Submitted solutions:

code_snippet: #include<bits/stdc++.h>
#define MAX 1024
#define inf 1<<29
#define linf (1e16)
#define eps (1e-8)
#define Eps (1e-15)
#define mod 1000000007
#define pi acos(-1.0)
#define phi (1.0+sqrt(5.0))/2.0
#define f first
#define s second
#define mp make_pair
#define pb push_back
#define all(a) (a).begin(),(a).end()
#define pd(a) printf("%.10f\n",(double)(a))
#define pld(a) printf("%.10Lf\n",(ld)(a))
#define FOR(i,a,b) for(int i=(a);i<(b);i++)
#define RFOR(i,a,b) for(int i=(a)-1;(b)<=i;i--)
#define Unique(v) v.erase(unique(all(v)),v.end())
#define equals(a,b) (fabs((a)-(b))<eps)
using namespace std;
typedef long double ld;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pii;
typedef pair<int,double> pid;
typedef pair<double,int> pdi;
typedef pair<double,double> pdd;
typedef vector<int> vi;
typedef vector<pii> vpi;

class Point{
public:
  double x,y;
  Point(double x=0,double y=0):x(x),y(y){}

  Point operator+(Point p){ return Point(x+p.x,y+p.y);}
  Point operator-(Point p){ return Point(x-p.x,y-p.y);}
  Point operator*(double k){ return Point(x*k,y*k);}
  Point operator/(double k){ return Point(x/k,y/k);}
  bool operator<(Point p)const{ 
    return equals(x,p.x) ? y-p.y<-eps : x-p.x<-eps; }
  bool operator==(Point p)const{ 
    return fabs(x-p.x)<eps && fabs(y-p.y)<eps;}

  double abs(){ return sqrt(norm());}
  double norm(){ return (x*x+y*y);}
};
typedef Point Vector;
typedef vector<Point> Polygon;

class Segment{
public:
  Point p1,p2;
  Segment(Point p1=Point(),Point p2=Point()):p1(p1),p2(p2){}
};
typedef Segment Line;

class Circle{
public:
  Point c;
  double r;
  Circle(Point c=Point(),double r=0.0):c(c),r(r){}
};

double norm(Vector a){ return (a.x*a.x+a.y*a.y);}
double abs(Vector a){ return sqrt(norm(a));}
double dot(Vector a,Vector b){ return (a.x*b.x+a.y*b.y);}
double cross(Vector a,Vector b){ return (a.x*b.y-a.y*b.x);}
double arg(Vector p){ return atan2(p.y,p.x);}
Vector polar(double a,double r){ return Point(cos(r)*a,sin(r)*a);}

class Dedge{
  public:
  int s,t,f,l;
  ld r;
  Dedge(int s,int t,ld r):s(s),t(t),f(0),l(0){
    while(pi<r)r-=2.0*pi;
    while(r<-pi)r+=2.0*pi;
    this->r=r;
  }
  bool operator==(Dedge e)const{ return t==e.t; }
  bool operator<(Dedge e)const{ return r>e.r; }
  bool operator<(ld R)const{ return r>R; }
};

class DualGraph{
  public:
  int n;
  vector<Point> v;
  vector<Polygon> P;
  vector<vector<Dedge> > g;

  DualGraph(vector<Point> v):v(v),g(v.size()),n(v.size()){}

  void add_edge(int s,int t){
    ld r=arg(v[t]-v[s]);
    g[s].pb(Dedge(s,t,r));
    g[t].pb(Dedge(t,s,r+pi));
  }

  void add_polygon(int s,int t,ld r){
    vector<Dedge>::iterator e=lower_bound(all(g[s]),r-eps);
    if(e==g[s].end())e=g[s].begin();
    if(e->f)return;
    e->f=1;
    e->l=t;
    P[t].pb(v[s]);
    add_polygon(e->t, t, e->r > 0 ? e->r-pi : e->r+pi);
  }

  vector<Polygon> dual(){
    FOR(i,0,n){ sort(all(g[i])); Unique(g[i]); }
    FOR(i,0,n){
      FOR(j,0,g[i].size()){
        if(!g[i][j].f){
          P.pb(Polygon());
          add_polygon(i,P.size()-1,g[i][j].r+eps);
        }
      }
    }
    return P;
  }
};

bool on(Circle c,Point p){ return equals(abs(c.c-p),c.r); }

int intersect(Circle a,Circle b){
  double d=abs(a.c-b.c);
  if(a.r<b.r)swap(a,b);
  if(a.r+b.r+eps<d)return 2;
  if(a.r+b.r-eps<d)return 1;
  if(a.r-b.r+eps<d)return 0;
  if(a.r-b.r-eps<d)return -1;
  return -2;
}

pair<Point,Point> getCrossPoints(Circle c1,Circle c2){
  double d=abs(c1.c-c2.c);
  double a=acos((c1.r*c1.r+d*d-c2.r*c2.r)/(2.0*c1.r*d));
  double t=arg(c2.c-c1.c);
  return mp(c1.c+polar(c1.r,t+a),c1.c+polar(c1.r,t-a));
}

Point rotate(Point base,Point a,double r){
  Point b=a-base;
  a.x=b.x*cos((r/180.0)*pi)-b.y*sin((r/180.0)*pi);
  a.y=b.x*sin((r/180.0)*pi)+b.y*cos((r/180.0)*pi);
  a=a+base;
  return a;
}

double getAngle(Vector a,Vector b){
  double tmp=dot(a,b)/(abs(a)*abs(b));
  if(tmp<-1.0)tmp=-1.0;
  if(1.0<tmp)tmp=1.0;
  double r=acos(tmp)*180.0/pi;
  if(cross(a,b)<-eps)r=360.0-r;
  return r;
}

double Area(Polygon p){
  double area=0.0;
  int n=p.size();
  for(int i=0;i<n;i++)area+=cross(p[i],p[(i+1)%n]);
  return area/2.0;
}

int contains(Polygon g,Point p){
  int n=g.size();
  bool x=false;
  for(int i=0;i<n;i++){
    Vector a=g[i]-p,b=g[(i+1)%n]-p;
    if(abs(cross(a,b))<eps && dot(a,b)<eps)return 1;
    if(a.y>b.y)swap(a,b);
    if(a.y<eps && eps<b.y && cross(a,b)>eps)x=!x;
  }
  if(x)return 2;
  return 0;
}

vector<Polygon> remove(vector<Polygon> p){
  vector<Polygon> res;
  FOR(i,0,p.size())if(eps<Area(p[i]))res.pb(p[i]);
  return res;
}

struct edge{ int to,cap,rev; };

int n,k;
vector<Circle> vc;
vector<Polygon> v;
vector<edge> G[MAX];
bool used[MAX];
bool in[MAX][MAX];
bool adj[MAX][MAX];

void add_edge(int from,int to,int cap){
  G[from].push_back((edge){to,cap,(int)G[to].size()});
  G[to].push_back((edge){from,0,(int)G[from].size()-1});
}
 
int dfs(int v,int t,int f){
  if(v==t)return f;
  used[v]=true;
  for(int i=0;i<G[v].size();i++){
    edge &e=G[v][i];
    if(!used[e.to] && e.cap>0){
      int d=dfs(e.to,t,min(f,e.cap));
      if(d>0){
    e.cap-=d;
    G[e.to][e.rev].cap+=d;
    return d;
      }
    }
  }
  return 0;
}
 
int max_flow(int s,int t){
  int flow=0;
  for(;;){
    fill(used,used+MAX,0);
    int f=dfs(s,t,inf);
    if(f==0)return flow;
    flow+=f;
  }
}

bool same(Point a,Point b,Point c,Point d){
  return ((a==c && b==d) || (a==d && b==c));
}

bool check1(Polygon a,Polygon b){
  FOR(i,0,a.size())
    FOR(j,0,b.size())
      if(same(a[i],a[(i+1)%a.size()],b[j],b[(j+1)%b.size()]))
        return true;
  return false;
}

bool check2(Polygon a,Polygon b){
  FOR(i,0,a.size())
    if(contains(b,a[i])!=2)return false;
  return true;
}

int cal(){
  int V=v.size();
  int s=2*V,t=s+1;
  FOR(i,0,V){
    add_edge(s,i,1);
    add_edge(i+V,t,1);
  }
  FOR(i,0,V){
    FOR(j,0,V){
      if(i==j)continue;
      adj[i][j]=check1(v[i],v[j]);
      in[i][j]=check2(v[i],v[j]);
    }
  }
  FOR(i,0,V)
    FOR(j,0,V)
      if(in[i][j])
        FOR(k,0,V)
          if(in[i][k] && in[k][j])
            in[i][j]=false;

  FOR(i,0,V)
    FOR(j,0,V)
      if(adj[i][j] || in[i][j] || in[j][i])add_edge(i,j+V,1);
  return V-max_flow(s,t)/2;
}

int solve(){
  vector<Point> vp,tmp;
  FOR(i,0,n){
    vp.pb(Point(vc[i].c.x+vc[i].r,vc[i].c.y));
    vp.pb(Point(vc[i].c.x-vc[i].r,vc[i].c.y));
    vp.pb(Point(vc[i].c.x,vc[i].c.y+vc[i].r));
    vp.pb(Point(vc[i].c.x,vc[i].c.y-vc[i].r));
    FOR(j,i+1,n){
      if(abs(intersect(vc[i],vc[j]))==2)continue;
      pair<Point,Point> pp=getCrossPoints(vc[i],vc[j]);
      vp.pb(pp.f);
      vp.pb(pp.s);
    }
  }
  FOR(i,0,n){
    vector<pair<double,Point> > list;
    FOR(j,0,vp.size()){
      double rarg=arg(vp[j]-vc[i].c);
      if(rarg<-eps)rarg+=2.0*pi;
      if(on(vc[i],vp[j]))list.pb(mp(rarg,vp[j]));
    }
    sort(all(list));
    FOR(j,0,list.size()){
      Point a=list[j].s,b=list[(j+1)%list.size()].s;
      double r=getAngle(a-vc[i].c,b-vc[i].c);
      tmp.pb(rotate(vc[i].c,a,r/2.0));
    }
  }
  FOR(i,0,tmp.size())vp.pb(tmp[i]);
  sort(all(vp));
  Unique(vp);
  DualGraph dg=DualGraph(vp);
  FOR(i,0,n){
    vector<pair<double,int> > list;
    FOR(j,0,vp.size()){
      double rarg=arg(vp[j]-vc[i].c);
      if(rarg<-eps)rarg+=2.0*pi;
      if(on(vc[i],vp[j]))list.pb(mp(rarg,j));
    }
    sort(all(list));
    FOR(j,0,list.size()){
      int a=list[j].s,b=list[(j+1)%list.size()].s;
      dg.add_edge(a,b);
    }
  }
  v=dg.dual();
  v=remove(v);
  if(1<k)return v.size();
  return cal();
}

int main()
{
  cin>>n>>k;
  vc.resize(n);
  FOR(i,0,n)cin>>vc[i].c.x>>vc[i].c.y>>vc[i].r;
  cout<<solve()<<endl;
  return 0;
}
accuracy: 1
time_ms: 110
memory_kb: 4556
final_rank: 3

code_snippet: #include<bits/stdc++.h>
#define MAX 1200
#define inf 1<<29
#define linf (1e16)
#define eps (1e-8)
#define Eps (1e-15)
#define mod 1000000007
#define pi acos(-1.0)
#define phi (1.0+sqrt(5.0))/2.0
#define f first
#define s second
#define mp make_pair
#define pb push_back
#define all(a) (a).begin(),(a).end()
#define pd(a) printf("%.10f\n",(double)(a))
#define pld(a) printf("%.10Lf\n",(ld)(a))
#define FOR(i,a,b) for(int i=(a);i<(b);i++)
#define RFOR(i,a,b) for(int i=(a)-1;(b)<=i;i--)
#define Unique(v) v.erase(unique(all(v)),v.end())
#define equals(a,b) (fabs((a)-(b))<eps)
using namespace std;
typedef long double ld;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pii;
typedef pair<int,double> pid;
typedef pair<double,int> pdi;
typedef pair<double,double> pdd;
typedef vector<int> vi;
typedef vector<pii> vpi;

class Point{
public:
  double x,y;
  Point(double x=0,double y=0):x(x),y(y){}

  Point operator+(Point p){ return Point(x+p.x,y+p.y);}
  Point operator-(Point p){ return Point(x-p.x,y-p.y);}
  Point operator*(double k){ return Point(x*k,y*k);}
  Point operator/(double k){ return Point(x/k,y/k);}
  bool operator<(Point p)const{ 
    return equals(x,p.x) ? y-p.y<-eps : x-p.x<-eps; }
  bool operator==(Point p)const{ 
    return fabs(x-p.x)<eps && fabs(y-p.y)<eps;}

  double abs(){ return sqrt(norm());}
  double norm(){ return (x*x+y*y);}
};
typedef Point Vector;
typedef vector<Point> Polygon;

class Segment{
public:
  Point p1,p2;
  Segment(Point p1=Point(),Point p2=Point()):p1(p1),p2(p2){}
};
typedef Segment Line;

class Circle{
public:
  Point c;
  double r;
  Circle(Point c=Point(),double r=0.0):c(c),r(r){}
};

double norm(Vector a){ return (a.x*a.x+a.y*a.y);}
double abs(Vector a){ return sqrt(norm(a));}
double dot(Vector a,Vector b){ return (a.x*b.x+a.y*b.y);}
double cross(Vector a,Vector b){ return (a.x*b.y-a.y*b.x);}
double arg(Vector p){ return atan2(p.y,p.x);}
Vector polar(double a,double r){ return Point(cos(r)*a,sin(r)*a);}

class Dedge{
  public:
  int s,t,f,l;
  ld r;
  Dedge(int s,int t,ld r):s(s),t(t),f(0),l(0){
    while(pi<r)r-=2.0*pi;
    while(r<-pi)r+=2.0*pi;
    this->r=r;
  }
  bool operator==(Dedge e)const{ return t==e.t; }
  bool operator<(Dedge e)const{ return r>e.r; }
  bool operator<(ld R)const{ return r>R; }
};

class DualGraph{
  public:
  int n;
  vector<Point> v;
  vector<Polygon> P;
  vector<vector<Dedge> > g;

  DualGraph(vector<Point> v):v(v),g(v.size()),n(v.size()){}

  void add_edge(int s,int t){
    ld r=arg(v[t]-v[s]);
    g[s].pb(Dedge(s,t,r));
    g[t].pb(Dedge(t,s,r+pi));
  }

  void add_polygon(int s,int t,ld r){
    vector<Dedge>::iterator e=lower_bound(all(g[s]),r-eps);
    if(e==g[s].end())e=g[s].begin();
    if(e->f)return;
    e->f=1;
    e->l=t;
    P[t].pb(v[s]);
    add_polygon(e->t, t, e->r > 0 ? e->r-pi : e->r+pi);
  }

  vector<Polygon> dual(){
    FOR(i,0,n){ sort(all(g[i])); Unique(g[i]); }
    FOR(i,0,n){
      FOR(j,0,g[i].size()){
        if(!g[i][j].f){
          P.pb(Polygon());
          add_polygon(i,P.size()-1,g[i][j].r+eps);
        }
      }
    }
    return P;
  }
};

bool on(Circle c,Point p){ return equals(abs(c.c-p),c.r); }

int intersect(Circle a,Circle b){
  double d=abs(a.c-b.c);
  if(a.r<b.r)swap(a,b);
  if(a.r+b.r+eps<d)return 2;
  if(a.r+b.r-eps<d)return 1;
  if(a.r-b.r+eps<d)return 0;
  if(a.r-b.r-eps<d)return -1;
  return -2;
}

pair<Point,Point> getCrossPoints(Circle c1,Circle c2){
  double d=abs(c1.c-c2.c);
  double a=acos((c1.r*c1.r+d*d-c2.r*c2.r)/(2.0*c1.r*d));
  double t=arg(c2.c-c1.c);
  return mp(c1.c+polar(c1.r,t+a),c1.c+polar(c1.r,t-a));
}

Point rotate(Point base,Point a,double r){
  Point b=a-base;
  a.x=b.x*cos((r/180.0)*pi)-b.y*sin((r/180.0)*pi);
  a.y=b.x*sin((r/180.0)*pi)+b.y*cos((r/180.0)*pi);
  a=a+base;
  return a;
}

double getAngle(Vector a,Vector b){
  double tmp=dot(a,b)/(abs(a)*abs(b));
  if(tmp<-1.0)tmp=-1.0;
  if(1.0<tmp)tmp=1.0;
  double r=acos(tmp)*180.0/pi;
  if(cross(a,b)<-eps)r=360.0-r;
  return r;
}

double Area(Polygon p){
  double area=0.0;
  int n=p.size();
  for(int i=0;i<n;i++)area+=cross(p[i],p[(i+1)%n]);
  return area/2.0;
}

int contains(Polygon g,Point p){
  int n=g.size();
  bool x=false;
  for(int i=0;i<n;i++){
    Vector a=g[i]-p,b=g[(i+1)%n]-p;
    if(abs(cross(a,b))<eps && dot(a,b)<eps)return 1;
    if(a.y>b.y)swap(a,b);
    if(a.y<eps && eps<b.y && cross(a,b)>eps)x=!x;
  }
  if(x)return 2;
  return 0;
}

vector<Polygon> remove(vector<Polygon> p){
  vector<Polygon> res;
  FOR(i,0,p.size())if(eps<Area(p[i]))res.pb(p[i]);
  return res;
}

struct edge{ int to,cap,rev; };

int n,k;
vector<Circle> vc;
vector<Polygon> v;
vector<edge> G[MAX];
bool used[MAX];
bool in[MAX][MAX];
bool adj[MAX][MAX];

void add_edge(int from,int to,int cap){
  G[from].push_back((edge){to,cap,(int)G[to].size()});
  G[to].push_back((edge){from,0,(int)G[from].size()-1});
}
 
int dfs(int v,int t,int f){
  if(v==t)return f;
  used[v]=true;
  for(int i=0;i<G[v].size();i++){
    edge &e=G[v][i];
    if(!used[e.to] && e.cap>0){
      int d=dfs(e.to,t,min(f,e.cap));
      if(d>0){
    e.cap-=d;
    G[e.to][e.rev].cap+=d;
    return d;
      }
    }
  }
  return 0;
}
 
int max_flow(int s,int t){
  int flow=0;
  for(;;){
    fill(used,used+MAX,0);
    int f=dfs(s,t,inf);
    if(f==0)return flow;
    flow+=f;
  }
}

bool same(Point a,Point b,Point c,Point d){
  return ((a==c && b==d) || (a==d && b==c));
}

bool check1(Polygon a,Polygon b){
  FOR(i,0,a.size())
    FOR(j,0,b.size())
      if(same(a[i],a[(i+1)%a.size()],b[j],b[(j+1)%b.size()]))
        return true;
  return false;
}

bool check2(Polygon a,Polygon b){
  FOR(i,0,a.size())
    if(contains(b,a[i])!=2)return false;
  return true;
}

int cal(){
  int V=v.size();
  int s=2*V,t=s+1;
  FOR(i,0,V){
    add_edge(s,i,1);
    add_edge(i+V,t,1);
  }
  FOR(i,0,V){
    FOR(j,0,V){
      if(i==j)continue;
      adj[i][j]=check1(v[i],v[j]);
      in[i][j]=check2(v[i],v[j]);
    }
  }
  FOR(i,0,V)
    FOR(j,0,V)
      if(in[i][j])
        FOR(k,0,V)
          if(in[i][k] && in[k][j])
            in[i][j]=false;

  FOR(i,0,V)
    FOR(j,0,V)
      if(adj[i][j] || in[i][j] || in[j][i])add_edge(i,j+V,1);
  return V-max_flow(s,t)/2;
}

int solve(){
  vector<Point> vp,tmp;
  FOR(i,0,n){
    vp.pb(Point(vc[i].c.x+vc[i].r,vc[i].c.y));
    vp.pb(Point(vc[i].c.x-vc[i].r,vc[i].c.y));
    vp.pb(Point(vc[i].c.x,vc[i].c.y+vc[i].r));
    vp.pb(Point(vc[i].c.x,vc[i].c.y-vc[i].r));
    FOR(j,i+1,n){
      if(abs(intersect(vc[i],vc[j]))==2)continue;
      pair<Point,Point> pp=getCrossPoints(vc[i],vc[j]);
      vp.pb(pp.f);
      vp.pb(pp.s);
    }
  }
  FOR(i,0,n){
    vector<pair<double,Point> > list;
    FOR(j,0,vp.size()){
      double rarg=arg(vp[j]-vc[i].c);
      if(rarg<-eps)rarg+=2.0*pi;
      if(on(vc[i],vp[j]))list.pb(mp(rarg,vp[j]));
    }
    sort(all(list));
    FOR(j,0,list.size()){
      Point a=list[j].s,b=list[(j+1)%list.size()].s;
      double r=getAngle(a-vc[i].c,b-vc[i].c);
      tmp.pb(rotate(vc[i].c,a,r/2.0));
    }
  }
  FOR(i,0,tmp.size())vp.pb(tmp[i]);
  sort(all(vp));
  Unique(vp);
  DualGraph dg=DualGraph(vp);
  FOR(i,0,n){
    vector<pair<double,int> > list;
    FOR(j,0,vp.size()){
      double rarg=arg(vp[j]-vc[i].c);
      if(rarg<-eps)rarg+=2.0*pi;
      if(on(vc[i],vp[j]))list.pb(mp(rarg,j));
    }
    sort(all(list));
    FOR(j,0,list.size()){
      int a=list[j].s,b=list[(j+1)%list.size()].s;
      dg.add_edge(a,b);
    }
  }
  v=dg.dual();
  v=remove(v);
  if(1<k)return v.size();
  return cal();
}

int main()
{
  cin>>n>>k;
  vc.resize(n);
  FOR(i,0,n)cin>>vc[i].c.x>>vc[i].c.y>>vc[i].r;
  cout<<solve()<<endl;
  return 0;
}
accuracy: 1
time_ms: 110
memory_kb: 4660
final_rank: 4

code_snippet: #include<bits/stdc++.h>
#define MAX 32
#define inf 1<<29
#define linf (1e16)
#define eps (1e-10)
#define Eps (1e-15)
#define mod 1000000007
#define pi acos(-1.0)
#define phi (1.0+sqrt(5.0))/2.0
#define f first
#define s second
#define mp make_pair
#define pb push_back
#define all(a) (a).begin(),(a).end()
#define pd(a) printf("%.10f\n",(double)(a))
#define pld(a) printf("%.10Lf\n",(ld)(a))
#define FOR(i,a,b) for(int i=(a);i<(b);i++)
#define RFOR(i,a,b) for(int i=(a)-1;(b)<=i;i--)
#define Unique(v) v.erase(unique(all(v)),v.end())
#define equals(a,b) (fabs((a)-(b))<eps)
using namespace std;
typedef long double ld;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pii;
typedef pair<int,double> pid;
typedef pair<double,int> pdi;
typedef pair<double,double> pdd;
typedef vector<int> vi;
typedef vector<pii> vpi;

class Point{
public:
  double x,y;
  Point(double x=0,double y=0):x(x),y(y){}

  Point operator+(Point p){ return Point(x+p.x,y+p.y);}
  Point operator-(Point p){ return Point(x-p.x,y-p.y);}
  Point operator*(double k){ return Point(x*k,y*k);}
  Point operator/(double k){ return Point(x/k,y/k);}
  bool operator<(Point p)const{ 
    return equals(x,p.x) ? y-p.y<-eps : x-p.x<-eps; }
  bool operator==(Point p)const{ 
    return fabs(x-p.x)<eps && fabs(y-p.y)<eps;}

  double abs(){ return sqrt(norm());}
  double norm(){ return (x*x+y*y);}
};
typedef Point Vector;
typedef vector<Point> Polygon;

class Segment{
public:
  Point p1,p2;
  Segment(Point p1=Point(),Point p2=Point()):p1(p1),p2(p2){}
};
typedef Segment Line;

class Circle{
public:
  Point c;
  double r;
  Circle(Point c=Point(),double r=0.0):c(c),r(r){}
};

double norm(Vector a){ return (a.x*a.x+a.y*a.y);}
double abs(Vector a){ return sqrt(norm(a));}
double dot(Vector a,Vector b){ return (a.x*b.x+a.y*b.y);}
double cross(Vector a,Vector b){ return (a.x*b.y-a.y*b.x);}
double arg(Vector p){ return atan2(p.y,p.x);}
Vector polar(double a,double r){ return Point(cos(r)*a,sin(r)*a);}

class Dedge{
  public:
  int s,t,f,l;
  ld r;
  Dedge(int s,int t,ld r):s(s),t(t),f(0),l(0){
    while(pi<r)r-=2.0*pi;
    while(r<-pi)r+=2.0*pi;
    this->r=r;
  }
  bool operator==(Dedge e)const{ return t==e.t; }
  bool operator<(Dedge e)const{ return r>e.r; }
  bool operator<(ld R)const{ return r>R; }
};

class DualGraph{
  public:
  int n;
  vector<Point> v;
  vector<Polygon> P;
  vector<vector<Dedge> > g;

  DualGraph(vector<Point> v):v(v),g(v.size()),n(v.size()){}

  void add_edge(int s,int t){
    ld r=arg(v[t]-v[s]);
    g[s].pb(Dedge(s,t,r));
    g[t].pb(Dedge(t,s,r+pi));
  }

  void add_polygon(int s,int t,ld r){
    vector<Dedge>::iterator e=lower_bound(all(g[s]),r-eps);
    if(e==g[s].end())e=g[s].begin();
    if(e->f)return;
    e->f=1;
    e->l=t;
    P[t].pb(v[s]);
    add_polygon(e->t, t, e->r > 0 ? e->r-pi : e->r+pi);
  }

  vector<Polygon> dual(){
    FOR(i,0,n){ sort(all(g[i])); Unique(g[i]); }
    FOR(i,0,n){
      FOR(j,0,g[i].size()){
        if(!g[i][j].f){
          P.pb(Polygon());
          add_polygon(i,P.size()-1,g[i][j].r+eps);
        }
      }
    }
    return P;
  }
};

bool on(Circle c,Point p){ return equals(abs(c.c-p),c.r); }

int intersect(Circle a,Circle b){
  double d=abs(a.c-b.c);
  if(a.r<b.r)swap(a,b);
  if(a.r+b.r+eps<d)return 2;
  if(a.r+b.r-eps<d)return 1;
  if(a.r-b.r+eps<d)return 0;
  if(a.r-b.r-eps<d)return -1;
  return -2;
}

pair<Point,Point> getCrossPoints(Circle c1,Circle c2){
  double d=abs(c1.c-c2.c);
  double a=acos((c1.r*c1.r+d*d-c2.r*c2.r)/(2.0*c1.r*d));
  double t=arg(c2.c-c1.c);
  return mp(c1.c+polar(c1.r,t+a),c1.c+polar(c1.r,t-a));
}

Point rotate(Point base,Point a,double r){
  Point b=a-base;
  a.x=b.x*cos((r/180.0)*pi)-b.y*sin((r/180.0)*pi);
  a.y=b.x*sin((r/180.0)*pi)+b.y*cos((r/180.0)*pi);
  a=a+base;
  return a;
}

double getAngle(Vector a,Vector b){
  double tmp=dot(a,b)/(abs(a)*abs(b));
  if(tmp<-1.0)tmp=-1.0;
  if(1.0<tmp)tmp=1.0;
  double r=acos(tmp)*180.0/pi;
  if(cross(a,b)<-eps)r=360.0-r;
  return r;
}

double Area(Polygon p){
  double area=0.0;
  int n=p.size();
  for(int i=0;i<n;i++)area+=cross(p[i],p[(i+1)%n]);
  return area/2.0;
}

int contains(Polygon g,Point p){
  int n=g.size();
  bool x=false;
  for(int i=0;i<n;i++){
    Vector a=g[i]-p,b=g[(i+1)%n]-p;
    if(abs(cross(a,b))<eps && dot(a,b)<eps)return 1;
    if(a.y>b.y)swap(a,b);
    if(a.y<eps && eps<b.y && cross(a,b)>eps)x=!x;
  }
  if(x)return 2;
  return 0;
}

vector<Polygon> remove(vector<Polygon> p){
  vector<Polygon> res;
  FOR(i,0,p.size())if(eps<Area(p[i]))res.pb(p[i]);
  return res;
}

void P(Polygon p){
  cout<<endl<<p.size()<<endl;
  FOR(i,0,p.size())cout<<p[i].x<<" "<<p[i].y<<endl;
}

struct edge{ int to,cap,rev; };

int n,k;
vector<Circle> vc;
vector<Polygon> v;
vector<edge> G[2002];
bool used[2002];
bool in[2002][2002];
bool adj[2002][2002];

void add_edge(int from,int to,int cap){
  G[from].push_back((edge){to,cap,(int)G[to].size()});
  G[to].push_back((edge){from,0,(int)G[from].size()-1});
}
 
int dfs(int v,int t,int f){
  if(v==t)return f;
  used[v]=true;
  for(int i=0;i<G[v].size();i++){
    edge &e=G[v][i];
    if(!used[e.to] && e.cap>0){
      int d=dfs(e.to,t,min(f,e.cap));
      if(d>0){
    e.cap-=d;
    G[e.to][e.rev].cap+=d;
    return d;
      }
    }
  }
  return 0;
}
 
int max_flow(int s,int t){
  int flow=0;
  for(;;){
    fill(used,used+2002,0);
    int f=dfs(s,t,inf);
    if(f==0)return flow;
    flow+=f;
  }
}

bool same(Point a,Point b,Point c,Point d){
  return ((a==c && b==d) || (a==d && b==c));
}

bool check1(Polygon a,Polygon b){
  FOR(i,0,a.size())
    FOR(j,0,b.size())
      if(same(a[i],a[(i+1)%a.size()],b[j],b[(j+1)%b.size()]))
        return true;
  return false;
}

bool check2(Polygon a,Polygon b){
  FOR(i,0,a.size())
    if(contains(b,a[i])!=2)return false;
  return true;
}

int cal(){
  int V=v.size();
  int s=2*V,t=s+1;
  FOR(i,0,V){
    add_edge(s,i,1);
    add_edge(i+V,t,1);
  }
  FOR(i,0,V){
    FOR(j,0,V){
      if(i==j)continue;
      adj[i][j]=check1(v[i],v[j]);
      in[i][j]=check2(v[i],v[j]);
//      if(in[i][j])P(v[i]);
    }
  }

  FOR(i,0,V)
    FOR(j,0,V)
      if(in[i][j])
        FOR(k,0,V)
          if(in[i][j] && in[i][k] && in[k][j])
            in[i][j]=false;

  FOR(i,0,V)
    FOR(j,0,V)
      if(adj[i][j] || in[i][j] || in[j][i])add_edge(i,j+V,1);
  return V-max_flow(s,t)/2;
}

int solve(){
  vector<Point> vp,tmp;
  FOR(i,0,n){
    vp.pb(Point(vc[i].c.x+vc[i].r,vc[i].c.y));
    vp.pb(Point(vc[i].c.x-vc[i].r,vc[i].c.y));
    vp.pb(Point(vc[i].c.x,vc[i].c.y+vc[i].r));
    vp.pb(Point(vc[i].c.x,vc[i].c.y-vc[i].r));
    FOR(j,i+1,n){
      if(abs(intersect(vc[i],vc[j]))==2)continue;
      pair<Point,Point> pp=getCrossPoints(vc[i],vc[j]);
      vp.pb(pp.f);
      vp.pb(pp.s);
    }
  }
  FOR(i,0,n){
    vector<pair<double,Point> > list;
    FOR(j,0,vp.size()){
      double rarg=arg(vp[j]-vc[i].c);
      if(rarg<-eps)rarg+=2.0*pi;
      if(on(vc[i],vp[j]))list.pb(mp(rarg,vp[j]));
    }
    sort(all(list));
    FOR(j,0,list.size()){
      Point a=list[j].s,b=list[(j+1)%list.size()].s;
      double r=getAngle(a-vc[i].c,b-vc[i].c);
      tmp.pb(rotate(vc[i].c,a,r/2.0));
    }
  }
  FOR(i,0,tmp.size())vp.pb(tmp[i]);
  sort(all(vp));
  Unique(vp);
  DualGraph dg=DualGraph(vp);
  FOR(i,0,n){
    vector<pair<double,int> > list;
    FOR(j,0,vp.size()){
      double rarg=arg(vp[j]-vc[i].c);
      if(rarg<-eps)rarg+=2.0*pi;
      if(on(vc[i],vp[j]))list.pb(mp(rarg,j));
    }
    sort(all(list));
    FOR(j,0,list.size()){
      int a=list[j].s,b=list[(j+1)%list.size()].s;
      dg.add_edge(a,b);
    }
  }
  v=dg.dual();
  v=remove(v);
  if(1<k)return v.size();
  return cal();
}

int main()
{
  cin>>n>>k;
  vc.resize(n);
  FOR(i,0,n)cin>>vc[i].c.x>>vc[i].c.y>>vc[i].r;
  cout<<solve()<<endl;
  return 0;
}
accuracy: 1
time_ms: 110
memory_kb: 5084
final_rank: 5

code_snippet: // Go to hell

#include<bits/stdc++.h>
#define MAX 32
#define inf 1<<29
#define linf (1e16)
#define eps (1e-6)
#define Eps (1e-15)
#define mod 1000000007
#define pi acos(-1.0)
#define phi (1.0+sqrt(5.0))/2.0
#define f first
#define s second
#define mp make_pair
#define pb push_back
#define all(a) (a).begin(),(a).end()
#define pd(a) printf("%.10f\n",(double)(a))
#define pld(a) printf("%.10Lf\n",(ld)(a))
#define FOR(i,a,b) for(int i=(a);i<(b);i++)
#define RFOR(i,a,b) for(int i=(a)-1;(b)<=i;i--)
#define Unique(v) v.erase(unique(all(v)),v.end())
#define equals(a,b) (fabs((a)-(b))<eps)
using namespace std;
typedef long double ld;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pii;
typedef pair<int,double> pid;
typedef pair<double,int> pdi;
typedef pair<double,double> pdd;
typedef vector<int> vi;
typedef vector<pii> vpi;

class Point{
public:
  double x,y;
  Point(double x=0,double y=0):x(x),y(y){}

  Point operator+(Point p){ return Point(x+p.x,y+p.y);}
  Point operator-(Point p){ return Point(x-p.x,y-p.y);}
  Point operator*(double k){ return Point(x*k,y*k);}
  Point operator/(double k){ return Point(x/k,y/k);}
  bool operator<(Point p)const{ 
    return equals(x,p.x) ? y-p.y<-eps : x-p.x<-eps; }
  bool operator==(Point p)const{ 
    return fabs(x-p.x)<eps && fabs(y-p.y)<eps;}

  double abs(){ return sqrt(norm());}
  double norm(){ return (x*x+y*y);}
};
typedef Point Vector;
typedef vector<Point> Polygon;

class Segment{
public:
  Point p1,p2;
  Segment(Point p1=Point(),Point p2=Point()):p1(p1),p2(p2){}
};
typedef Segment Line;

class Circle{
public:
  Point c;
  double r;
  Circle(Point c=Point(),double r=0.0):c(c),r(r){}
};

double norm(Vector a){ return (a.x*a.x+a.y*a.y);}
double abs(Vector a){ return sqrt(norm(a));}
double dot(Vector a,Vector b){ return (a.x*b.x+a.y*b.y);}
double cross(Vector a,Vector b){ return (a.x*b.y-a.y*b.x);}
double arg(Vector p){ return atan2(p.y,p.x);}
Vector polar(double a,double r){ return Point(cos(r)*a,sin(r)*a);}

class Dedge{
  public:
  int s,t,f,l;
  ld r;
  Dedge(int s,int t,ld r):s(s),t(t),f(0),l(0){
    while(pi<r)r-=2.0*pi;
    while(r<-pi)r+=2.0*pi;
    this->r=r;
  }
  bool operator==(Dedge e)const{ return t==e.t; }
  bool operator<(Dedge e)const{ return r>e.r; }
  bool operator<(ld R)const{ return r>R; }
};

class DualGraph{
  public:
  int n;
  vector<Point> v;
  vector<Polygon> P;
  vector<vector<Dedge> > g;

  DualGraph(vector<Point> v):v(v),g(v.size()),n(v.size()){}

  void add_edge(int s,int t){
    ld r=arg(v[t]-v[s]);
    g[s].pb(Dedge(s,t,r));
    g[t].pb(Dedge(t,s,r+pi));
  }

  void add_polygon(int s,int t,ld r){
    vector<Dedge>::iterator e=lower_bound(all(g[s]),r-eps);
    if(e==g[s].end())e=g[s].begin();
    if(e->f)return;
    e->f=1;
    e->l=t;
    P[t].pb(v[s]);
    add_polygon(e->t, t, e->r > 0 ? e->r-pi : e->r+pi);
  }

  vector<Polygon> dual(){
    FOR(i,0,n){ sort(all(g[i])); Unique(g[i]); }
    FOR(i,0,n){
      FOR(j,0,g[i].size()){
        if(!g[i][j].f){
          P.pb(Polygon());
          add_polygon(i,P.size()-1,g[i][j].r+eps);
        }
      }
    }
    return P;
  }
};

bool on(Circle c,Point p){ return equals(abs(c.c-p),c.r); }

int intersect(Circle a,Circle b){
  double d=abs(a.c-b.c);
  if(a.r<b.r)swap(a,b);
  if(a.r+b.r+eps<=d)return 2;
  if(a.r+b.r-eps<=d)return 1;
  if(a.r-b.r+eps<=d)return 0;
  if(a.r-b.r-eps<=d)return -1;
  return -2;
}

pair<Point,Point> getCrossPoints(Circle c1,Circle c2){
  double d=abs(c1.c-c2.c);
  double a=acos((c1.r*c1.r+d*d-c2.r*c2.r)/(2.0*c1.r*d));
  double t=arg(c2.c-c1.c);
  return mp(c1.c+polar(c1.r,t+a),c1.c+polar(c1.r,t-a));
}

Point rotate(Point base,Point a,double r){
  Point b=a-base;
  a.x=b.x*cos((r/180.0)*pi)-b.y*sin((r/180.0)*pi);
  a.y=b.x*sin((r/180.0)*pi)+b.y*cos((r/180.0)*pi);
  a=a+base;
  return a;
}

double getAngle(Vector a,Vector b){
  double tmp=dot(a,b)/(abs(a)*abs(b));
  if(tmp<-1.0)tmp=-1.0;
  if(1.0<tmp)tmp=1.0;
  double r=acos(tmp)*180.0/pi;
  if(cross(a,b)<-eps)r=360.0-r;
  return r;
}

double Area(Polygon p){
  double area=0.0;
  int n=p.size();
  for(int i=0;i<n;i++)area+=cross(p[i],p[(i+1)%n]);
  return area/2.0;
}

int contains(Polygon g,Point p){
  int n=g.size();
  bool x=false;
  for(int i=0;i<n;i++){
    Vector a=g[i]-p,b=g[(i+1)%n]-p;
    if(abs(cross(a,b))<eps && dot(a,b)<eps)return 1;
    if(a.y>b.y)swap(a,b);
    if(a.y<eps && eps<b.y && cross(a,b)>eps)x=!x;
  }
  if(x)return 2;
  return 0;
}

vector<Polygon> remove(vector<Polygon> p){
  vector<Polygon> res;
  FOR(i,0,p.size())if(eps<Area(p[i]))res.pb(p[i]);
  return res;
}

void P(Polygon p){
  cout<<endl<<p.size()<<endl;
  FOR(i,0,p.size())cout<<p[i].x<<" "<<p[i].y<<endl;
}

struct edge{ int to,cap,rev; };

int n,k;
vector<Circle> vc;
vector<Polygon> v;
vector<edge> G[2002];
bool used[2002];
bool in[2002][2002];
bool adj[2002][2002];

void add_edge(int from,int to,int cap){
  G[from].push_back((edge){to,cap,(int)G[to].size()});
  G[to].push_back((edge){from,0,(int)G[from].size()-1});
}
 
int dfs(int v,int t,int f){
  if(v==t)return f;
  used[v]=true;
  for(int i=0;i<G[v].size();i++){
    edge &e=G[v][i];
    if(!used[e.to] && e.cap>0){
      int d=dfs(e.to,t,min(f,e.cap));
      if(d>0){
    e.cap-=d;
    G[e.to][e.rev].cap+=d;
    return d;
      }
    }
  }
  return 0;
}
 
int max_flow(int s,int t){
  int flow=0;
  for(;;){
    memset(used,0,sizeof(used));
    int f=dfs(s,t,inf);
    if(f==0)return flow;
    flow+=f;
  }
}

bool same(Point a,Point b,Point c,Point d){
  return ((a==c && b==d) || (a==d && b==c));
}

bool check1(Polygon a,Polygon b){
  FOR(i,0,a.size())
    FOR(j,0,b.size())
      if(same(a[i],a[(i+1)%a.size()],b[j],b[(j+1)%b.size()]))
        return true;
  return false;
}

bool check2(Polygon a,Polygon b){
  FOR(i,0,a.size())
    if(contains(b,a[i])==0)return false;
  return true;
}

int cal(){
  int V=v.size();
  int s=2*V,t=s+1;
  FOR(i,0,V)add_edge(s,i,1);
  FOR(i,0,V)add_edge(i+V,t,1);
  FOR(i,0,V){
    FOR(j,0,V){
      if(i==j)continue;
      adj[i][j]=check1(v[i],v[j]);
      in[i][j]=check2(v[i],v[j]);
    }
  }
  FOR(i,0,V)
    FOR(j,0,V)
      if(in[i][j])
        FOR(k,0,V)
          if(in[i][k] && in[k][j])
            in[i][j]=false;

  FOR(i,0,V)
    FOR(j,0,V)
      if(adj[i][j] || in[i][j] || in[j][i])add_edge(i,j+V,1);
  return V-max_flow(s,t)/2;
}

int solve(){
  vector<Point> vp,tmp;
  FOR(i,0,n){
    vp.pb(Point(vc[i].c.x+vc[i].r,vc[i].c.y));
    vp.pb(Point(vc[i].c.x-vc[i].r,vc[i].c.y));
    FOR(j,i+1,n){
      if(abs(intersect(vc[i],vc[j]))==2)continue;
      pair<Point,Point> pp=getCrossPoints(vc[i],vc[j]);
      vp.pb(pp.f);
      vp.pb(pp.s);
    }
  }
  FOR(i,0,n){
    vector<pair<double,Point> > list;
    FOR(j,0,vp.size()){
      double rarg=arg(vp[j]-vc[i].c);
      if(rarg<-eps)rarg+=2.0*pi;
      if(on(vc[i],vp[j]))list.pb(mp(rarg,vp[j]));
    }
    sort(all(list));
    FOR(j,0,list.size()){
      Point a=list[j].s,b=list[(j+1)%list.size()].s;
      double r=getAngle(a-vc[i].c,b-vc[i].c);
      tmp.pb(rotate(vc[i].c,a,r/2.0));
    }
  }
  FOR(i,0,tmp.size())vp.pb(tmp[i]);
  sort(all(vp));
  Unique(vp);
  DualGraph dg=DualGraph(vp);
  FOR(i,0,n){
    vector<pair<double,int> > list;
    FOR(j,0,vp.size()){
      double rarg=arg(vp[j]-vc[i].c);
      if(rarg<-eps)rarg+=2.0*pi;
      if(on(vc[i],vp[j]))list.pb(mp(rarg,j));
    }
    sort(all(list));
    FOR(j,0,list.size()){
      int a=list[j].s,b=list[(j+1)%list.size()].s;
      dg.add_edge(a,b);
    }
  }
  v=dg.dual();
  v=remove(v);
  if(1<k)return v.size();
  return cal();
}

int main()
{
  cin>>n>>k;
  vc.resize(n);
  FOR(i,0,n)cin>>vc[i].c.x>>vc[i].c.y>>vc[i].r;
  cout<<solve()<<endl;
  return 0;
}
accuracy: 0.425531914893617
time_ms: 100
memory_kb: 5192
final_rank: 9

code_snippet: #include<bits/stdc++.h>
#define MAX 22
#define inf 1<<29
#define linf (1e16)
#define eps (1e-10)
#define Eps (1e-15)
#define mod 1000000007
#define pi acos(-1.0)
#define phi (1.0+sqrt(5.0))/2.0
#define f first
#define s second
#define mp make_pair
#define pb push_back
#define all(a) (a).begin(),(a).end()
#define pd(a) printf("%.10f\n",(double)(a))
#define pld(a) printf("%.10Lf\n",(ld)(a))
#define FOR(i,a,b) for(int i=(a);i<(b);i++)
#define RFOR(i,a,b) for(int i=(a)-1;(b)<=i;i--)
#define Unique(v) v.erase(unique(all(v)),v.end())
#define equals(a,b) (fabs((a)-(b))<eps)
using namespace std;
typedef long double ld;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pii;
typedef pair<int,double> pid;
typedef pair<double,int> pdi;
typedef pair<double,double> pdd;
typedef vector<int> vi;
typedef vector<pii> vpi;

class Point{
public:
  double x,y;
  Point(double x=0,double y=0):x(x),y(y){}

  Point operator+(Point p){ return Point(x+p.x,y+p.y);}
  Point operator-(Point p){ return Point(x-p.x,y-p.y);}
  Point operator*(double k){ return Point(x*k,y*k);}
  Point operator/(double k){ return Point(x/k,y/k);}
  bool operator<(Point p)const{ 
    return equals(x,p.x) ? y-p.y<-eps : x-p.x<-eps; }
  bool operator==(Point p)const{ 
    return fabs(x-p.x)<eps && fabs(y-p.y)<eps;}

  double abs(){ return sqrt(norm());}
  double norm(){ return (x*x+y*y);}
};
typedef Point Vector;
typedef vector<Point> Polygon;

class Segment{
public:
  Point p1,p2;
  Segment(Point p1=Point(),Point p2=Point()):p1(p1),p2(p2){}
};
typedef Segment Line;

class Circle{
public:
  Point c;
  double r;
  Circle(Point c=Point(),double r=0.0):c(c),r(r){}
};

double norm(Vector a){ return (a.x*a.x+a.y*a.y);}
double abs(Vector a){ return sqrt(norm(a));}
double dot(Vector a,Vector b){ return (a.x*b.x+a.y*b.y);}
double cross(Vector a,Vector b){ return (a.x*b.y-a.y*b.x);}
double arg(Vector p){ return atan2(p.y,p.x);}
Vector polar(double a,double r){ return Point(cos(r)*a,sin(r)*a);}

class Dedge{
  public:
  int s,t,f,l;
  ld r;
  Dedge(int s,int t,ld r):s(s),t(t),f(0),l(0){
    while(pi<r)r-=2.0*pi;
    while(r<-pi)r+=2.0*pi;
    this->r=r;
  }
  bool operator==(Dedge e)const{ return t==e.t; }
  bool operator<(Dedge e)const{ return r>e.r; }
  bool operator<(ld R)const{ return r>R; }
};

class DualGraph{
  public:
  int n;
  vector<Point> v;
  vector<Polygon> P;
  vector<vector<Dedge> > g;

  DualGraph(vector<Point> v):v(v),g(v.size()),n(v.size()){}

  void add_edge(int s,int t){
    ld r=arg(v[t]-v[s]);
    g[s].pb(Dedge(s,t,r));
    g[t].pb(Dedge(t,s,r+pi));
  }

  void add_polygon(int s,int t,ld r){
    vector<Dedge>::iterator e=lower_bound(all(g[s]),r-eps);
    if(e==g[s].end())e=g[s].begin();
    if(e->f)return;
    e->f=1;
    e->l=t;
    P[t].pb(v[s]);
    add_polygon(e->t, t, e->r > 0 ? e->r-pi : e->r+pi);
  }

  vector<Polygon> dual(){
    FOR(i,0,n){ sort(all(g[i])); Unique(g[i]); }
    FOR(i,0,n){
      FOR(j,0,g[i].size()){
        if(!g[i][j].f){
          P.pb(Polygon());
          add_polygon(i,P.size()-1,g[i][j].r+eps);
        }
      }
    }
    return P;
  }
};


bool on(Circle c,Point p){ return equals(abs(c.c-p),c.r); }

int intersect(Circle a,Circle b){
  double d=abs(a.c-b.c);
  if(a.r<b.r)swap(a,b);
  if(a.r+b.r+eps<=d)return 2;
  if(a.r+b.r-eps<=d)return 1;
  if(a.r-b.r+eps<=d)return 0;
  if(a.r-b.r-eps<=d)return -1;
  return -2;
}

pair<Point,Point> getCrossPoints(Circle c1,Circle c2){
  double d=abs(c1.c-c2.c);
  double a=acos((c1.r*c1.r+d*d-c2.r*c2.r)/(2.0*c1.r*d));
  double t=arg(c2.c-c1.c);
  return mp(c1.c+polar(c1.r,t+a),c1.c+polar(c1.r,t-a));
}

Point rotate(Point base,Point a,double r){
  Point b=a-base;
  a.x=b.x*cos((r/180.0)*pi)-b.y*sin((r/180.0)*pi);
  a.y=b.x*sin((r/180.0)*pi)+b.y*cos((r/180.0)*pi);
  a=a+base;
  return a;
}

double getAngle(Vector a,Vector b){
  double tmp=dot(a,b)/(abs(a)*abs(b));
  if(tmp<-1.0)tmp=-1.0;
  if(1.0<tmp)tmp=1.0;
  double r=acos(tmp)*180.0/pi;
  if(cross(a,b)<-eps)r=360.0-r;
  return r;
}

double Area(Polygon p){
  double area=0.0;
  int n=p.size();
  for(int i=0;i<n;i++)area+=cross(p[i],p[(i+1)%n]);
  return area/2.0;
}

int contains(Polygon g,Point p){
  int n=g.size();
  bool x=false;
  for(int i=0;i<n;i++){
    Vector a=g[i]-p,b=g[(i+1)%n]-p;
    if(abs(cross(a,b))<eps && dot(a,b)<eps)return 1;
    if(a.y>b.y)swap(a,b);
    if(a.y<eps && eps<b.y && cross(a,b)>eps)x=!x;
  }
  if(x)return 2;
  return 0;
}

bool same(Point a,Point b,Point c,Point d){
  return ((a==c && b==d) || (a==d && b==c)); 
}

bool check(Polygon a,Polygon b){
  FOR(i,0,a.size())
    if(contains(b,a[i]+(a[(i+1)%a.size()]-a[i])/2.0)!=0)return true;
  FOR(i,0,b.size())
    if(contains(a,b[i]+(b[(i+1)%b.size()]-b[i])/2.0)!=0)return true;
  return false;
}

vector<Polygon> remove(vector<Polygon> p){
  vector<Polygon> res;
  FOR(i,0,p.size())if(eps<Area(p[i]))res.pb(p[i]);
  return res;
}

struct edge{ int to,cap,rev; };

int n,k;
vector<Circle> vc;
vector<edge> G[2002];
bool used[2002];

void add_edge(int from,int to,int cap){
  G[from].push_back((edge){to,cap,(int)G[to].size()});
  G[to].push_back((edge){from,0,(int)G[from].size()-1});
}
 
int dfs(int v,int t,int f){
  if(v==t)return f;
  used[v]=true;
  for(int i=0;i<G[v].size();i++){
    edge &e=G[v][i];
    if(!used[e.to] && e.cap>0){
      int d=dfs(e.to,t,min(f,e.cap));
      if(d>0){
    e.cap-=d;
    G[e.to][e.rev].cap+=d;
    return d;
      }
    }
  }
  return 0;
}
 
int max_flow(int s,int t){
  int flow=0;
  for(;;){
    memset(used,0,sizeof(used));
    int f=dfs(s,t,inf);
    if(f==0)return flow;
    flow+=f;
  }
}

int cal(vector<Polygon> vp){
  int V=vp.size();
  int s=2*V,t=s+1;
  FOR(i,0,V)add_edge(s,i,1);
  FOR(i,0,V)add_edge(i+V,t,1);
  FOR(i,0,V){
    FOR(j,0,V){
      if(i==j)continue;
      if(check(vp[i],vp[j]))add_edge(i,j+V,1);
    }
  }
  return V-max_flow(s,t)/2;
}

int solve(){
  vector<Point> vp,tmp;
  FOR(i,0,n){
    vp.pb(Point(vc[i].c.x+vc[i].r,vc[i].c.y));
    vp.pb(Point(vc[i].c.x-vc[i].r,vc[i].c.y));
    FOR(j,i+1,n){
      if(abs(intersect(vc[i],vc[j]))==2)continue;
      pair<Point,Point> pp=getCrossPoints(vc[i],vc[j]);
      vp.pb(pp.f);
      vp.pb(pp.s);
    }
  }
  FOR(i,0,n){
    vector<pair<double,Point> > list;
    FOR(j,0,vp.size()){
      double rarg=arg(vp[j]-vc[i].c);
      if(rarg<-eps)rarg+=2.0*pi;
      if(on(vc[i],vp[j]))list.pb(mp(rarg,vp[j]));
    }
    sort(all(list));
    FOR(j,0,list.size()){
      Point a=list[j].s,b=list[(j+1)%list.size()].s;
      double r=getAngle(a-vc[i].c,b-vc[i].c);
      tmp.pb(rotate(vc[i].c,a,r/2.0));
    }
  }
  FOR(i,0,tmp.size())vp.pb(tmp[i]);
  sort(all(vp));
  Unique(vp);
  DualGraph dg=DualGraph(vp);
  FOR(i,0,n){
    vector<pair<double,int> > list;
    FOR(j,0,vp.size()){
      double rarg=arg(vp[j]-vc[i].c);
      if(rarg<-eps)rarg+=2.0*pi;
      if(on(vc[i],vp[j]))list.pb(mp(rarg,j));
    }
    sort(all(list));
    FOR(j,0,list.size()){
      int a=list[j].s,b=list[(j+1)%list.size()].s;
      dg.add_edge(a,b);
    }
  }
  vector<Polygon> v=dg.dual();
  v=remove(v);
  if(1<k)return v.size();
  return cal(v);
}

int main()
{
  cin>>n>>k;
  vc.resize(n);
  FOR(i,0,n)cin>>vc[i].c.x>>vc[i].c.y>>vc[i].r;
  cout<<solve()<<endl;
  return 0;
}
accuracy: 0.425531914893617
time_ms: 130
memory_kb: 4224
final_rank: 10

code_snippet: #include<bits/stdc++.h>
#define MAX 22
#define inf 1<<29
#define linf (1e16)
#define eps (1e-8)
#define Eps (1e-15)
#define mod 1000000007
#define pi acos(-1.0)
#define phi (1.0+sqrt(5.0))/2.0
#define f first
#define s second
#define mp make_pair
#define pb push_back
#define all(a) (a).begin(),(a).end()
#define pd(a) printf("%.10f\n",(double)(a))
#define pld(a) printf("%.10Lf\n",(ld)(a))
#define FOR(i,a,b) for(int i=(a);i<(b);i++)
#define RFOR(i,a,b) for(int i=(a)-1;(b)<=i;i--)
#define Unique(v) v.erase(unique(all(v)),v.end())
#define equals(a,b) (fabs((a)-(b))<eps)
using namespace std;
typedef long double ld;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pii;
typedef pair<int,double> pid;
typedef pair<double,int> pdi;
typedef pair<double,double> pdd;
typedef vector<int> vi;
typedef vector<pii> vpi;

class Point{
public:
  double x,y;
  Point(double x=0,double y=0):x(x),y(y){}

  Point operator+(Point p){ return Point(x+p.x,y+p.y);}
  Point operator-(Point p){ return Point(x-p.x,y-p.y);}
  Point operator*(double k){ return Point(x*k,y*k);}
  Point operator/(double k){ return Point(x/k,y/k);}
  bool operator<(Point p)const{ 
    return equals(x,p.x) ? y-p.y<-eps : x-p.x<-eps; }
  bool operator==(Point p)const{ 
    return fabs(x-p.x)<eps && fabs(y-p.y)<eps;}

  double abs(){ return sqrt(norm());}
  double norm(){ return (x*x+y*y);}
};
typedef Point Vector;
typedef vector<Point> Polygon;

class Segment{
public:
  Point p1,p2;
  Segment(Point p1=Point(),Point p2=Point()):p1(p1),p2(p2){}
};
typedef Segment Line;

class Circle{
public:
  Point c;
  double r;
  Circle(Point c=Point(),double r=0.0):c(c),r(r){}
};

double norm(Vector a){ return (a.x*a.x+a.y*a.y);}
double abs(Vector a){ return sqrt(norm(a));}
double dot(Vector a,Vector b){ return (a.x*b.x+a.y*b.y);}
double cross(Vector a,Vector b){ return (a.x*b.y-a.y*b.x);}
double arg(Vector p){ return atan2(p.y,p.x);}
Vector polar(double a,double r){ return Point(cos(r)*a,sin(r)*a);}

class Dedge{
  public:
  int s,t,f,l;
  ld r;
  Dedge(int s,int t,ld r):s(s),t(t),f(0),l(0){
    while(pi<r)r-=2.0*pi;
    while(r<-pi)r+=2.0*pi;
    this->r=r;
  }
  bool operator==(Dedge e)const{ return t==e.t; }
  bool operator<(Dedge e)const{ return r>e.r; }
  bool operator<(ld R)const{ return r>R; }
};

class DualGraph{
  public:
  int n;
  vector<Point> v;
  vector<Polygon> P;
  vector<vector<Dedge> > g;

  DualGraph(vector<Point> v):v(v),g(v.size()),n(v.size()){}

  void add_edge(int s,int t){
    ld r=arg(v[t]-v[s]);
    g[s].pb(Dedge(s,t,r));
    g[t].pb(Dedge(t,s,r+pi));
  }

  void add_polygon(int s,int t,ld r){
    vector<Dedge>::iterator e=lower_bound(all(g[s]),r-eps);
    if(e==g[s].end())e=g[s].begin();
    if(e->f)return;
    e->f=1;
    e->l=t;
    P[t].pb(v[s]);
    add_polygon(e->t, t, e->r > 0 ? e->r-pi : e->r+pi);
  }

  vector<Polygon> dual(){
    FOR(i,0,n){ sort(all(g[i])); Unique(g[i]); }
    FOR(i,0,n){
      FOR(j,0,g[i].size()){
        if(!g[i][j].f){
          P.pb(Polygon());
          add_polygon(i,P.size()-1,g[i][j].r+eps);
        }
      }
    }
    return P;
  }
};


bool on(Circle c,Point p){ return equals(abs(c.c-p),c.r); }

int intersect(Circle a,Circle b){
  double d=abs(a.c-b.c);
  if(a.r<b.r)swap(a,b);
  if(a.r+b.r+eps<=d)return 2;
  if(a.r+b.r-eps<=d)return 1;
  if(a.r-b.r+eps<=d)return 0;
  if(a.r-b.r-eps<=d)return -1;
  return -2;
}

pair<Point,Point> getCrossPoints(Circle c1,Circle c2){
  double d=abs(c1.c-c2.c);
  double a=acos((c1.r*c1.r+d*d-c2.r*c2.r)/(2.0*c1.r*d));
  double t=arg(c2.c-c1.c);
  return mp(c1.c+polar(c1.r,t+a),c1.c+polar(c1.r,t-a));
}

Point rotate(Point base,Point a,double r){
  Point b=a-base;
  a.x=b.x*cos((r/180.0)*pi)-b.y*sin((r/180.0)*pi);
  a.y=b.x*sin((r/180.0)*pi)+b.y*cos((r/180.0)*pi);
  a=a+base;
  return a;
}

double getAngle(Vector a,Vector b){
  double tmp=dot(a,b)/(abs(a)*abs(b));
  if(tmp<-1.0)tmp=-1.0;
  if(1.0<tmp)tmp=1.0;
  double r=acos(tmp)*180.0/pi;
  if(cross(a,b)<-eps)r=360.0-r;
  return r;
}

double Area(Polygon p){
  double area=0.0;
  int n=p.size();
  for(int i=0;i<n;i++)area+=cross(p[i],p[(i+1)%n]);
  return area/2.0;
}

int contains(Polygon g,Point p){
  int n=g.size();
  bool x=false;
  for(int i=0;i<n;i++){
    Vector a=g[i]-p,b=g[(i+1)%n]-p;
    if(abs(cross(a,b))<eps && dot(a,b)<eps)return 1;
    if(a.y>b.y)swap(a,b);
    if(a.y<eps && eps<b.y && cross(a,b)>eps)x=!x;
  }
  if(x)return 2;
  return 0;
}

bool same(Point a,Point b,Point c,Point d){
  return ((a==c && b==d) || (a==d && b==c)); 
}

bool check(Polygon a,Polygon b){
  FOR(i,0,a.size())
    if(contains(b,a[i]+(a[(i+1)%a.size()]-a[i])/2.0)!=0)return true;
  FOR(i,0,b.size())
    if(contains(a,b[i]+(b[(i+1)%b.size()]-b[i])/2.0)!=0)return true;
//  FOR(i,0,a.size())
//    FOR(j,0,b.size())
//      if(same(a[i],a[(i+1)%a.size()],b[j],b[(j+1)%b.size()]))
//        return true;
    
  return false;
}

vector<Polygon> remove(vector<Polygon> p){
  vector<Polygon> res;
  FOR(i,0,p.size())if(eps<Area(p[i]))res.pb(p[i]);
  return res;
}

struct edge{ int to,cap,rev; };

int n,k;
vector<Circle> vc;
vector<edge> G[2002];
bool used[2002];

void add_edge(int from,int to,int cap){
  G[from].push_back((edge){to,cap,(int)G[to].size()});
  G[to].push_back((edge){from,0,(int)G[from].size()-1});
}
 
int dfs(int v,int t,int f){
  if(v==t)return f;
  used[v]=true;
  for(int i=0;i<G[v].size();i++){
    edge &e=G[v][i];
    if(!used[e.to] && e.cap>0){
      int d=dfs(e.to,t,min(f,e.cap));
      if(d>0){
    e.cap-=d;
    G[e.to][e.rev].cap+=d;
    return d;
      }
    }
  }
  return 0;
}
 
int max_flow(int s,int t){
  int flow=0;
  for(;;){
    memset(used,0,sizeof(used));
    int f=dfs(s,t,inf);
    if(f==0)return flow;
    flow+=f;
  }
}

int cal(vector<Polygon> vp){
  int V=vp.size();
  int s=2*V,t=s+1;
  FOR(i,0,V)add_edge(s,i,1);
  FOR(i,0,V)add_edge(i+V,t,1);
  FOR(i,0,V){
    FOR(j,0,V){
      if(i==j)continue;
      if(check(vp[i],vp[j]))add_edge(i,j+V,1);
    }
  }
  return V-max_flow(s,t)/2;
}

int solve(){
  vector<Point> vp,tmp;
  FOR(i,0,n){
    vp.pb(Point(vc[i].c.x+vc[i].r,vc[i].c.y));
    vp.pb(Point(vc[i].c.x-vc[i].r,vc[i].c.y));
    FOR(j,i+1,n){
      if(abs(intersect(vc[i],vc[j]))==2)continue;
      pair<Point,Point> pp=getCrossPoints(vc[i],vc[j]);
      vp.pb(pp.f);
      vp.pb(pp.s);
    }
  }
  FOR(i,0,n){
    vector<pair<double,Point> > list;
    FOR(j,0,vp.size()){
      double rarg=arg(vp[j]-vc[i].c);
      if(rarg<-eps)rarg+=2.0*pi;
      if(on(vc[i],vp[j]))list.pb(mp(rarg,vp[j]));
    }
    sort(all(list));
    FOR(j,0,list.size()){
      Point a=list[j].s,b=list[(j+1)%list.size()].s;
      double r=getAngle(a-vc[i].c,b-vc[i].c);
      tmp.pb(rotate(vc[i].c,a,r/2.0));
    }
  }
  FOR(i,0,tmp.size())vp.pb(tmp[i]);
  sort(all(vp));
  Unique(vp);
  DualGraph dg=DualGraph(vp);
  FOR(i,0,n){
    vector<pair<double,int> > list;
    FOR(j,0,vp.size()){
      double rarg=arg(vp[j]-vc[i].c);
      if(rarg<-eps)rarg+=2.0*pi;
      if(on(vc[i],vp[j]))list.pb(mp(rarg,j));
    }
    sort(all(list));
    FOR(j,0,list.size()){
      int a=list[j].s,b=list[(j+1)%list.size()].s;
      dg.add_edge(a,b);
    }
  }
  vector<Polygon> v=dg.dual();
  v=remove(v);
  if(1<k)return v.size();
  return cal(v);
}

int main()
{
  cin>>n>>k;
  vc.resize(n);
  FOR(i,0,n)cin>>vc[i].c.x>>vc[i].c.y>>vc[i].r;
  cout<<solve()<<endl;
  return 0;
}
accuracy: 0.425531914893617
time_ms: 110
memory_kb: 4208
final_rank: 8

code_snippet: #include<cstdio>
#include<utility>
#include<map>
#include<complex>
#include<cmath>
#include<vector>
#include<algorithm>

using namespace std;

typedef double Real;
typedef pair<Real,Real> P;
typedef complex<Real> Point;

void print(Point p, char ch = '\n'){
	printf("%f %f%c", p.real(), p.imag(), ch);
}

const Real epsL = 5e-4;

const Real eps = 1e-8;

template<class T> bool eq_(T a, T b){
	return abs(a - b) < eps;
}

template<class T> bool lt_(T a, T b){
	if(eq_(a, b)) return false;
	return a < b;
}

template<class T> bool le_(T a, T b){
	if(eq_(a, b)) return true;
	return a < b;
}

const Real PI = acos(-1.0);

Real normalize(Real x){
	while(x > PI) x -= PI * 2;
	while(x < -PI) x += PI * 2;
	return x;
}

Point toPt(P p){
	return Point(p.first, p.second);
}

P toP(Point pt){
	return P(pt.real(), pt.imag());
}

struct Circle:vector<Real>{
	vector<P> ps;
	Point c;
	Real r;
	Circle(){}
	Circle(Point p_,Real r_):c(p_),r(r_){}
};

int N;
Circle cs[22];

map<P, P> merged_pts;

void ins_point(Point pt){
	map<P, P>::iterator it = merged_pts.begin();
	P p = toP(pt);
	if(merged_pts.count(p) == 1) return;
	for(; it != merged_pts.end(); ++it){
		Real d = abs(toPt(it->first) - pt);
		P p2 = it->second;
		if(d < epsL){
			merged_pts[p] = p2;
			return;
		}
	}
	merged_pts[p] = p;
}

vector<Real> xs;

void iCC(Circle &c, Circle &c2){
	if(eq_(c.c, c2.c)) return;
	Real d = abs(c.c - c2.c);
	Real r = c.r, r2 = c2.r;
	if(lt_(r + r2, d)) return;//not touch
	else if(eq_(r + r2, d)){//out tangent
		Real ang = normalize(arg(c2.c - c.c));
		c.push_back(ang);
	}else if(lt_(abs(r - r2), d)){
		Real ang = arg(c2.c - c.c);
		Real ang2 = acos((r * r + d * d - r2 * r2) / (2.0 * r * d));
		c.push_back(normalize(ang + ang2));
		c.push_back(normalize(ang - ang2));
	}else if(eq_(abs(r - r2), d)){//in tangent
		if(r > r2){
			c.push_back(normalize(arg(c2.c - c.c)));
		}else{
			c.push_back(normalize(-arg(c2.c - c.c)));
		}
	}else{//contained
		return;
	}
}

void getAllPoints(){
	for(int i = 0; i < N; ++i){
		for(int j = 0; j < N; ++j){
			if(i == j) continue;
			iCC(cs[i], cs[j]);
		}
	}
	for(int i = 0; i < N; ++i){
		for(int j = 0; j < cs[i].size(); ++j){
			Real ang = cs[i][j];
			Point pt = cs[i].c + cs[i].r * Point(cos(ang), sin(ang));
			ins_point(pt);
		}
	}
}

void getPsCircle(Circle &c){
	sort(c.begin(), c.end());
	for(int i = 0; i < c.size(); ++i){
		Real ang = c[i];
		Point pt = c.c + c.r * Point(cos(ang), sin(ang));
		P p = merged_pts[toP(pt)];
		if(c.ps.size() == 0 || c.ps.back() != p){
			if(c.ps.size() != 0 && c.ps[0] == p) continue;
			c.ps.push_back(p);
		}
	}
}

void getPsAll(){
	for(int i = 0; i < N; ++i){
		getPsCircle(cs[i]);
	}
}

void getXs(){
	map<P, P> :: iterator it = merged_pts.begin();
	for(; it != merged_pts.end(); ++it){
		P p = it->second;
		xs.push_back(p.first);
	}
	for(int i = 0; i < N; ++i){
		xs.push_back(cs[i].c.real() - cs[i].r);
		xs.push_back(cs[i].c.real() + cs[i].r);
	}
	sort(xs.begin(), xs.end());
	xs.erase(unique(xs.begin(), xs.end()), xs.end());
}

//map<Real, vector<int> > ys[500];

vector<pair<Real, int> > ys[500];

void getYs(int id){
	Real x = xs[id];
	for(int i = 0; i < N; ++i){
		Circle &c = cs[i];
		if(c.c.real() - c.r == x){
		//	ys[id][c.c.imag()].push_back(i);
			ys[id].push_back(make_pair(c.c.imag(), i));
			ys[id].push_back(make_pair(c.c.imag(), i));
			continue;
		}else if(c.c.real() + c.r == x){
		//	ys[id][c.c.imag()].push_back(i);
			ys[id].push_back(make_pair(c.c.imag(), i));
			ys[id].push_back(make_pair(c.c.imag(), i));
			continue;
		}
		bool flg = false;
		for(int j = 0; j < c.ps.size(); ++j){
			if(c.ps[j].first == x){
				flg = true;
		//		ys[id][c.ps[j].second].push_back(i);
				ys[id].push_back(make_pair(c.ps[j].second, i));
				Real y1 = c.ps[j].second;
				Real y_mid = c.c.imag();
				Real y2 = y_mid * 2.0 - y1;
				ys[id].push_back(make_pair(y2, i));
				break;
			}
		}
		if(!flg){
			if(x < c.c.real() - c.r) continue;
			if(x > c.c.real() + c.r) continue;
			Real dx = abs(x - c.c.real());
			Real dy = sqrt(c.r * c.r - dx * dx);
		//	ys[id][c.c.imag() + dy].push_back(i);
		//	ys[id][c.c.imag() - dy].push_back(i);
			ys[id].push_back(make_pair(c.c.imag() + dy, i));
			ys[id].push_back(make_pair(c.c.imag() - dy, i));
		}
	}
	sort(ys[id].begin(), ys[id].end());
	/*for(int j = 0; j + 1 < ys[id].size(); ++j){
		Real y = ys[id][j].first;
		if(ys[id][j].first != ys[id][j + 1].first) continue;
		P p = P(xs[id], y);
		if(merged_pts.count(p) == 0){
			printf("no\n");
		}
	}*/
	/*printf("ys[%d]\n", id);
	for(int i = 0; i < ys[id].size(); ++i){
		printf("(%f, %d) ", ys[id][i].first, ys[id][i].second);
	}
	printf("\n");*/
}

void getYsAll(){
	for(int i = 0; i < xs.size(); ++i){
		getYs(i);
	}
}

typedef pair<Real, Real> PRR;

vector<PRR> arcs[500];

void getArcs(int id){
	vector<pair<Real, int> > &le = ys[id], &ri = ys[id + 1];
	for(int i = 0; i < N; ++i){
		const Real inf = 1e100;
		Real ly = inf, ry = inf;
		for(int j = 0; j < le.size(); ++j){
			if(le[j].second == i){
				ly = le[j].first;
				break;
			}
		}
		for(int j = 0; j < ri.size(); ++j){
			if(ri[j].second == i){
				ry = ri[j].first;
				break;
			}
		}
		if(ly == inf || ry == inf) continue;
		arcs[id].push_back(PRR(ly, ry));
		ly = inf, ry = inf;
		for(int j = (int)le.size() - 1; j >= 0; --j){
			if(le[j].second == i){
				ly = le[j].first;
				break;
			}
		}
		for(int j = (int)ri.size() - 1; j >= 0; --j){
			if(ri[j].second == i){
				ry = ri[j].first;
				break;
			}
		}
		arcs[id].push_back(PRR(ly, ry));
	}
	sort(arcs[id].begin(), arcs[id].end());
}

struct Region{
	int x_id;
	PRR lo, hi;
	Region(){}
	Region(int i, PRR prr1, PRR prr2){
		x_id = i;
		lo = prr1;
		hi = prr2;
		if(lo > hi) swap(lo, hi);
	}
};

vector<Region> regions;

struct UnionFind{
	int par[20200];
	void init(int N){
		for(int i = 0; i < N; ++i){
			par[i] = i;
		}
	}
	int find(int x){
		if(x == par[x]) return x;
		return par[x] = find(par[x]);
	}
	void unite(int x, int y){
	//	printf("unite %d %d\n", x, y);
		x = find(x), y = find(y);
		if(x == y) return;
		if(x > y) swap(x, y);
		par[y] = x;
	}
	bool same(int x, int y){
		return find(x) == find(y);
	}
};

UnionFind uf;

void getRegions(){
	for(int i = 0; i + 1 < xs.size(); ++i){
		getArcs(i);
	}
	for(int i = 0; i + 1 < xs.size(); ++i){
		for(int j = 0; j + 1 < arcs[i].size(); ++j){
			PRR lo = arcs[i][j];
			PRR hi = arcs[i][j + 1];
			regions.push_back(Region(i, lo, hi));
		}
	}
}

bool checkIntersect(Real l1, Real h1, Real l2, Real h2){
	if(h1 <= l2) return false;
	if(h2 <= l1) return false;
	if(l1 == h1) return false;
	if(l2 == h2) return false;
	return true;
}

void mergeRegions(){
	uf.init(regions.size());
	for(int i = 0; i < regions.size(); ++i){
		Region r = regions[i];
		for(int j = i - 1; j >= 0; --j){
			Region cur = regions[j];
			if(cur.x_id <= r.x_id - 2) break;
			if(cur.x_id == r.x_id) continue;
			bool flg = checkIntersect(r.lo.first, r.hi.first, cur.lo.second, cur.hi.second);
			if(flg){
				uf.unite(i, j);
			}
		}
		for(int j = i + 1; j < regions.size(); ++j){
			Region cur = regions[j];
			if(cur.x_id >= r.x_id + 2) break;
			if(cur.x_id == r.x_id) continue;
			bool flg = checkIntersect(r.lo.second, r.hi.second, cur.lo.first, cur.hi.first);
			if(flg){
				uf.unite(i, j);
			}
		}
	}
}

vector<int> G[20200];
bool is_valid[20200];

void getGraphVertices(){
	for(int i = 1; i < regions.size(); ++i){
		is_valid[i] = (uf.find(i) == i);
	//	if(is_valid[i]) printf("valid: %d\n", i);
	}
}

void getGraphEdges(){
	for(int i = 0; i + 1 < regions.size(); ++i){
		Region r1 = regions[i], r2 = regions[i + 1];
		if(r1.x_id != r2.x_id) continue;
		int u = uf.find(i), v = uf.find(i + 1);
		if(u == 0 || v == 0) continue;
		G[u].push_back(v);
		G[v].push_back(u);
	}
	for(int i = 0; i < regions.size(); ++i){
		sort(G[i].begin(), G[i].end());
		G[i].erase(unique(G[i].begin(), G[i].end()), G[i].end());
	}
}

void getGraph(){
	getGraphVertices();
	getGraphEdges();
}

int match[20200];
bool used[20200];

vector<int> valid_vs;
/*
bool dfs(int v, int p){
	used[v] = true;
	if(match[v] == -1 && p != -1){
		match[v] = p;
		return true;
	}
	if(match[v] == p){
		for(int i = 0; i < G[v].size(); ++i){
			int u = G[v][i];
			if(used[u]) continue;
			bool flg = dfs(u, v);
			if(flg){
				match[v] = u;
				return true;
			}
		}
	}else{
		int u = match[v];
		if(used[u]) return false;
		bool flg = dfs(u, v);
		if(flg){
			match[v] = p;
			return true;
		}
	}
	return false;
}*/

bool dfs(int v){
	used[v] = true;
	for(int i = 0; i < G[v].size(); ++i){
		int u = G[v][i];
		if(used[u]) continue;
		int w = match[u];
		if(w == -1){
			match[u] = v;
			match[v] = u;
			return true;
		}
		if(used[w]) continue;
		bool flg = dfs(w);
		if(flg){
			match[u] = v;
			match[v] = u;
			return true;
		}
	}
	return false;
}

int bipartiteMatching(){
	for(int i = 1; i < 20200; ++i){
		match[i] = -1;
		if(is_valid[i]){
			valid_vs.push_back(i);
		}
	}
	/*for(int i = 0; i < valid_vs.size(); ++i){
		printf("%d:", valid_vs[i]);
		for(int j = 0; j < G[valid_vs[i]].size(); ++j){
			printf("%d ", G[valid_vs[i]][j]);
		}
		printf("\n");
	}*/
	int res = 0;
	for(int i = 0; i < valid_vs.size(); ++i){
		int v = valid_vs[i];
		if(match[v] != -1) continue;
		for(int j = 0; j < valid_vs.size(); ++j){
			used[valid_vs[j]] = false;
		}
		bool flg = dfs(v);
		if(flg) res++;
	}
	//printf("match = %d\n", res);
	return res;
}

int K;

void rotAll(){
	Point r = Point(cos(1), sin(1));
	for(int i = 0; i < N; ++i){
		cs[i].c *= r;
	}
}

int solve(){
	rotAll();
	/*for(int i = 0; i < N; ++i){
		print(cs[i].c, ' ');
		printf("%f\n", cs[i].r);
	}*/
	getAllPoints();
	getPsAll();
	getXs();
	getYsAll();
	getRegions();
	mergeRegions();
	getGraph();
/*	for(int i = 0; i < xs.size(); ++i){
		printf("%f ", xs[i]);
	}
	printf("\n");
	for(int i = 0; i < regions.size(); ++i){
		Region r = regions[i];
		printf("x_id = %d\n", r.x_id);
		printf("%f %f %f %f\n", r.lo.first, r.lo.second, r.hi.first, r.hi.second);
	}*/
	int V = 0;
	for(int i = 0; i < 20200; ++i){
		if(is_valid[i]){
			V++;
		}
	}
	if(K >= 2){
		return V;
	}
	int ans = V - bipartiteMatching();
	return ans;
}

void input(){
	scanf("%d%d", &N, &K);
	for(int i = 0; i < N; ++i){
		int x, y, r;
		scanf("%d%d%d", &x, &y, &r);
		cs[i] = Circle(Point(x, y), r);
	}
	cs[N] = Circle(Point(0, 0), 5000);
	N++;
}

int main(){
	input();
	int ans = solve();
	printf("%d\n", ans);
	return 0;
}

/*
void iCC(Circle &c,Circle &c2){
	if(eq(c.c,c2.c)) return;
	Real d=abs(c.c-c2.c);
	Real r=c.r,r2=c2.r;
	if(sgn(d-(r+r2))>0) return;
	else if(sgn(d-(r+r2))==0){//out tangent
		Real ang=normalize(arg(c2.c-c.c));
		c.push_back(ang);
	}else if(sgn(d-abs(r-r2))>0){//intersect two points
		Real ang=arg(c2.c-c.c);
		Real ang2=acos((r*r+d*d-r2*r2)/(2*r*d));
		c.push_back(normalize(ang+ang2));
		c.push_back(normalize(ang-ang2));
	}else if(sgn(d-abs(r-r2))==0){//in tangent
		if(r>r2){
			c.push_back(normalize(arg(c2.c-c.c)));
		}else{
			c.push_back(normalize(-arg(c2.c-c.c)));
		}
	}else{//contained
		return;
	}
}*/
accuracy: 1
time_ms: 10
memory_kb: 2636
final_rank: 1

code_snippet: #include<cstdio>
#include<utility>
#include<map>
#include<complex>
#include<cmath>
#include<vector>
#include<algorithm>

using namespace std;

typedef long double Real;
typedef pair<Real,Real> P;
typedef complex<Real> Point;

void print(Point p, char ch = '\n'){
	printf("%f %f%c", p.real(), p.imag(), ch);
}

const Real epsL = 5e-4;

const Real eps = 1e-8;

template<class T> bool eq_(T a, T b){
	return abs(a - b) < eps;
}

template<class T> bool lt_(T a, T b){
	if(eq_(a, b)) return false;
	return a < b;
}

template<class T> bool le_(T a, T b){
	if(eq_(a, b)) return true;
	return a < b;
}

const Real PI = acos(-1.0);

Real normalize(Real x){
	while(x > PI) x -= PI * 2;
	while(x < -PI) x += PI * 2;
	return x;
}

Point toPt(P p){
	return Point(p.first, p.second);
}

P toP(Point pt){
	return P(pt.real(), pt.imag());
}

struct Circle:vector<Real>{
	vector<P> ps;
	Point c;
	Real r;
	Circle(){}
	Circle(Point p_,Real r_):c(p_),r(r_){}
};

int N;
Circle cs[22];

map<P, P> merged_pts;

void ins_point(Point pt){
	map<P, P>::iterator it = merged_pts.begin();
	P p = toP(pt);
	if(merged_pts.count(p) == 1) return;
	for(; it != merged_pts.end(); ++it){
		Real d = abs(toPt(it->first) - pt);
		P p2 = it->second;
		if(d < epsL){
			merged_pts[p] = p2;
			return;
		}
	}
	merged_pts[p] = p;
}

vector<Real> xs;

void iCC(Circle &c, Circle &c2){
	if(eq_(c.c, c2.c)) return;
	Real d = abs(c.c - c2.c);
	Real r = c.r, r2 = c2.r;
	if(lt_(r + r2, d)) return;//not touch
	else if(eq_(r + r2, d)){//out tangent
		Real ang = normalize(arg(c2.c - c.c));
		c.push_back(ang);
	}else if(lt_(abs(r - r2), d)){
		Real ang = arg(c2.c - c.c);
		Real ang2 = acos((r * r + d * d - r2 * r2) / (2.0 * r * d));
		c.push_back(normalize(ang + ang2));
		c.push_back(normalize(ang - ang2));
	}else if(eq_(abs(r - r2), d)){//in tangent
		if(r > r2){
			c.push_back(normalize(arg(c2.c - c.c)));
		}else{
			c.push_back(normalize(-arg(c2.c - c.c)));
		}
	}else{//contained
		return;
	}
}

void getAllPoints(){
	for(int i = 0; i < N; ++i){
		for(int j = 0; j < N; ++j){
			if(i == j) continue;
			iCC(cs[i], cs[j]);
		}
	}
	for(int i = 0; i < N; ++i){
		for(int j = 0; j < cs[i].size(); ++j){
			Real ang = cs[i][j];
			Point pt = cs[i].c + cs[i].r * Point(cos(ang), sin(ang));
			ins_point(pt);
		}
	}
}

void getPsCircle(Circle &c){
	sort(c.begin(), c.end());
	for(int i = 0; i < c.size(); ++i){
		Real ang = c[i];
		Point pt = c.c + c.r * Point(cos(ang), sin(ang));
		P p = merged_pts[toP(pt)];
		if(c.ps.size() == 0 || c.ps.back() != p){
			if(c.ps.size() != 0 && c.ps[0] == p) continue;
			c.ps.push_back(p);
		}
	}
}

void getPsAll(){
	for(int i = 0; i < N; ++i){
		getPsCircle(cs[i]);
	}
}

void getXs(){
	map<P, P> :: iterator it = merged_pts.begin();
	for(; it != merged_pts.end(); ++it){
		P p = it->second;
		xs.push_back(p.first);
	}
	for(int i = 0; i < N; ++i){
		xs.push_back(cs[i].c.real() - cs[i].r);
		xs.push_back(cs[i].c.real() + cs[i].r);
	}
	sort(xs.begin(), xs.end());
	xs.erase(unique(xs.begin(), xs.end()), xs.end());
}

//map<Real, vector<int> > ys[500];

vector<pair<Real, int> > ys[500];

void getYs(int id){
	Real x = xs[id];
	for(int i = 0; i < N; ++i){
		Circle &c = cs[i];
		if(c.c.real() - c.r == x){
		//	ys[id][c.c.imag()].push_back(i);
			ys[id].push_back(make_pair(c.c.imag(), i));
			ys[id].push_back(make_pair(c.c.imag(), i));
			continue;
		}else if(c.c.real() + c.r == x){
		//	ys[id][c.c.imag()].push_back(i);
			ys[id].push_back(make_pair(c.c.imag(), i));
			ys[id].push_back(make_pair(c.c.imag(), i));
			continue;
		}
		bool flg = false;
		for(int j = 0; j < c.ps.size(); ++j){
			if(c.ps[j].first == x){
				flg = true;
		//		ys[id][c.ps[j].second].push_back(i);
				ys[id].push_back(make_pair(c.ps[j].second, i));
				Real y1 = c.ps[j].second;
				Real y_mid = c.c.imag();
				Real y2 = y_mid * 2.0 - y1;
				ys[id].push_back(make_pair(y2, i));
				break;
			}
		}
		if(!flg){
			if(x < c.c.real() - c.r) continue;
			if(x > c.c.real() + c.r) continue;
			Real dx = abs(x - c.c.real());
			Real dy = sqrt(c.r * c.r - dx * dx);
		//	ys[id][c.c.imag() + dy].push_back(i);
		//	ys[id][c.c.imag() - dy].push_back(i);
			ys[id].push_back(make_pair(c.c.imag() + dy, i));
			ys[id].push_back(make_pair(c.c.imag() - dy, i));
		}
	}
	sort(ys[id].begin(), ys[id].end());
	/*for(int j = 0; j + 1 < ys[id].size(); ++j){
		Real y = ys[id][j].first;
		if(ys[id][j].first != ys[id][j + 1].first) continue;
		P p = P(xs[id], y);
		if(merged_pts.count(p) == 0){
			printf("no\n");
		}
	}*/
	/*printf("ys[%d]\n", id);
	for(int i = 0; i < ys[id].size(); ++i){
		printf("(%f, %d) ", ys[id][i].first, ys[id][i].second);
	}
	printf("\n");*/
}

void getYsAll(){
	for(int i = 0; i < xs.size(); ++i){
		getYs(i);
	}
}

typedef pair<Real, Real> PRR;

vector<PRR> arcs[500];

void getArcs(int id){
	vector<pair<Real, int> > &le = ys[id], &ri = ys[id + 1];
	for(int i = 0; i < N; ++i){
		const Real inf = 1e100;
		Real ly = inf, ry = inf;
		for(int j = 0; j < le.size(); ++j){
			if(le[j].second == i){
				ly = le[j].first;
				break;
			}
		}
		for(int j = 0; j < ri.size(); ++j){
			if(ri[j].second == i){
				ry = ri[j].first;
				break;
			}
		}
		if(ly == inf || ry == inf) continue;
		arcs[id].push_back(PRR(ly, ry));
		ly = inf, ry = inf;
		for(int j = (int)le.size() - 1; j >= 0; --j){
			if(le[j].second == i){
				ly = le[j].first;
				break;
			}
		}
		for(int j = (int)ri.size() - 1; j >= 0; --j){
			if(ri[j].second == i){
				ry = ri[j].first;
				break;
			}
		}
		arcs[id].push_back(PRR(ly, ry));
	}
	sort(arcs[id].begin(), arcs[id].end());
}

struct Region{
	int x_id;
	PRR lo, hi;
	Region(){}
	Region(int i, PRR prr1, PRR prr2){
		x_id = i;
		lo = prr1;
		hi = prr2;
		if(lo > hi) swap(lo, hi);
	}
};

vector<Region> regions;

struct UnionFind{
	int par[20200];
	void init(int N){
		for(int i = 0; i < N; ++i){
			par[i] = i;
		}
	}
	int find(int x){
		if(x == par[x]) return x;
		return par[x] = find(par[x]);
	}
	void unite(int x, int y){
	//	printf("unite %d %d\n", x, y);
		x = find(x), y = find(y);
		if(x == y) return;
		if(x > y) swap(x, y);
		par[y] = x;
	}
	bool same(int x, int y){
		return find(x) == find(y);
	}
};

UnionFind uf;

void getRegions(){
	for(int i = 0; i + 1 < xs.size(); ++i){
		getArcs(i);
	}
	for(int i = 0; i + 1 < xs.size(); ++i){
		for(int j = 0; j + 1 < arcs[i].size(); ++j){
			PRR lo = arcs[i][j];
			PRR hi = arcs[i][j + 1];
			regions.push_back(Region(i, lo, hi));
		}
	}
}

bool checkIntersect(Real l1, Real h1, Real l2, Real h2){
	if(h1 <= l2) return false;
	if(h2 <= l1) return false;
	if(l1 == h1) return false;
	if(l2 == h2) return false;
	return true;
}

void mergeRegions(){
	uf.init(regions.size());
	for(int i = 0; i < regions.size(); ++i){
		Region r = regions[i];
		for(int j = i - 1; j >= 0; --j){
			Region cur = regions[j];
			if(cur.x_id <= r.x_id - 2) break;
			if(cur.x_id == r.x_id) continue;
			bool flg = checkIntersect(r.lo.first, r.hi.first, cur.lo.second, cur.hi.second);
			if(flg){
				uf.unite(i, j);
			}
		}
		for(int j = i + 1; j < regions.size(); ++j){
			Region cur = regions[j];
			if(cur.x_id >= r.x_id + 2) break;
			if(cur.x_id == r.x_id) continue;
			bool flg = checkIntersect(r.lo.second, r.hi.second, cur.lo.first, cur.hi.first);
			if(flg){
				uf.unite(i, j);
			}
		}
	}
}

vector<int> G[20200];
bool is_valid[20200];

void getGraphVertices(){
	for(int i = 1; i < regions.size(); ++i){
		is_valid[i] = (uf.find(i) == i);
	//	if(is_valid[i]) printf("valid: %d\n", i);
	}
}

void getGraphEdges(){
	for(int i = 0; i + 1 < regions.size(); ++i){
		Region r1 = regions[i], r2 = regions[i + 1];
		if(r1.x_id != r2.x_id) continue;
		int u = uf.find(i), v = uf.find(i + 1);
		if(u == 0 || v == 0) continue;
		G[u].push_back(v);
		G[v].push_back(u);
	}
	for(int i = 0; i < regions.size(); ++i){
		sort(G[i].begin(), G[i].end());
		G[i].erase(unique(G[i].begin(), G[i].end()), G[i].end());
	}
}

void getGraph(){
	getGraphVertices();
	getGraphEdges();
}

int match[20200];
bool used[20200];

vector<int> valid_vs;
/*
bool dfs(int v, int p){
	used[v] = true;
	if(match[v] == -1 && p != -1){
		match[v] = p;
		return true;
	}
	if(match[v] == p){
		for(int i = 0; i < G[v].size(); ++i){
			int u = G[v][i];
			if(used[u]) continue;
			bool flg = dfs(u, v);
			if(flg){
				match[v] = u;
				return true;
			}
		}
	}else{
		int u = match[v];
		if(used[u]) return false;
		bool flg = dfs(u, v);
		if(flg){
			match[v] = p;
			return true;
		}
	}
	return false;
}*/

bool dfs(int v){
	used[v] = true;
	for(int i = 0; i < G[v].size(); ++i){
		int u = G[v][i];
		if(used[u]) continue;
		int w = match[u];
		if(w == -1){
			match[u] = v;
			match[v] = u;
			return true;
		}
		if(used[w]) continue;
		bool flg = dfs(w);
		if(flg){
			match[u] = v;
			match[v] = u;
			return true;
		}
	}
	return false;
}

int bipartiteMatching(){
	for(int i = 1; i < 20200; ++i){
		match[i] = -1;
		if(is_valid[i]){
			valid_vs.push_back(i);
		}
	}
	/*for(int i = 0; i < valid_vs.size(); ++i){
		printf("%d:", valid_vs[i]);
		for(int j = 0; j < G[valid_vs[i]].size(); ++j){
			printf("%d ", G[valid_vs[i]][j]);
		}
		printf("\n");
	}*/
	int res = 0;
	for(int i = 0; i < valid_vs.size(); ++i){
		int v = valid_vs[i];
		if(match[v] != -1) continue;
		for(int j = 0; j < valid_vs.size(); ++j){
			used[valid_vs[j]] = false;
		}
		bool flg = dfs(v);
		if(flg) res++;
	}
	//printf("match = %d\n", res);
	return res;
}

int K;

void rotAll(){
	Point r = Point(cos(1), sin(1));
	for(int i = 0; i < N; ++i){
		cs[i].c *= r;
	}
}

int solve(){
	rotAll();
	/*for(int i = 0; i < N; ++i){
		print(cs[i].c, ' ');
		printf("%f\n", cs[i].r);
	}*/
	getAllPoints();
	getPsAll();
	getXs();
	getYsAll();
	getRegions();
	mergeRegions();
	getGraph();
/*	for(int i = 0; i < xs.size(); ++i){
		printf("%f ", xs[i]);
	}
	printf("\n");
	for(int i = 0; i < regions.size(); ++i){
		Region r = regions[i];
		printf("x_id = %d\n", r.x_id);
		printf("%f %f %f %f\n", r.lo.first, r.lo.second, r.hi.first, r.hi.second);
	}*/
	int V = 0;
	for(int i = 0; i < 20200; ++i){
		if(is_valid[i]){
			V++;
		}
	}
	if(K >= 2){
		return V;
	}
	int ans = V - bipartiteMatching();
	return ans;
}

void input(){
	scanf("%d%d", &N, &K);
	for(int i = 0; i < N; ++i){
		int x, y, r;
		scanf("%d%d%d", &x, &y, &r);
		cs[i] = Circle(Point(x, y), r);
	}
	cs[N] = Circle(Point(0, 0), 5000);
	N++;
}

int main(){
	input();
	int ans = solve();
	printf("%d\n", ans);
	return 0;
}

/*
void iCC(Circle &c,Circle &c2){
	if(eq(c.c,c2.c)) return;
	Real d=abs(c.c-c2.c);
	Real r=c.r,r2=c2.r;
	if(sgn(d-(r+r2))>0) return;
	else if(sgn(d-(r+r2))==0){//out tangent
		Real ang=normalize(arg(c2.c-c.c));
		c.push_back(ang);
	}else if(sgn(d-abs(r-r2))>0){//intersect two points
		Real ang=arg(c2.c-c.c);
		Real ang2=acos((r*r+d*d-r2*r2)/(2*r*d));
		c.push_back(normalize(ang+ang2));
		c.push_back(normalize(ang-ang2));
	}else if(sgn(d-abs(r-r2))==0){//in tangent
		if(r>r2){
			c.push_back(normalize(arg(c2.c-c.c)));
		}else{
			c.push_back(normalize(-arg(c2.c-c.c)));
		}
	}else{//contained
		return;
	}
}*/
accuracy: 1
time_ms: 10
memory_kb: 3128
final_rank: 2

code_snippet: #include <cstdio>
#include <cmath>
#include <cstring>
#include <cstdlib>
#include <climits>
#include <ctime>
#include <queue>
#include <stack>
#include <algorithm>
#include <list>
#include <vector>
#include <set>
#include <map>
#include <iostream>
#include <deque>
#include <complex>
#include <string>
#include <iomanip>
#include <sstream>
#include <bitset>
#include <valarray>
#include <unordered_map>
#include <unordered_set>
#include <iterator>
#include <assert.h>
using namespace std;
typedef long long int ll;
typedef unsigned int uint;
typedef unsigned char uchar;
typedef unsigned long long ull;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef vector<int> vi;

#define REP(i,x) for(int i=0;i<(int)(x);i++)
#define REPS(i,x) for(int i=1;i<=(int)(x);i++)
#define RREP(i,x) for(int i=((int)(x)-1);i>=0;i--)
#define RREPS(i,x) for(int i=((int)(x));i>0;i--)
#define FOR(i,c) for(__typeof((c).begin())i=(c).begin();i!=(c).end();i++)
#define RFOR(i,c) for(__typeof((c).rbegin())i=(c).rbegin();i!=(c).rend();i++)
#define ALL(container) (container).begin(), (container).end()
#define RALL(container) (container).rbegin(), (container).rend()
#define SZ(container) ((int)container.size())
#define mp(a,b) make_pair(a, b)
#define UNIQUE(v) v.erase( unique(v.begin(), v.end()), v.end() );

template<class T> bool chmax(T &a, const T &b) { if (a<b) { a=b; return 1; } return 0; }
template<class T> bool chmin(T &a, const T &b) { if (a>b) { a=b; return 1; } return 0; }
template<class T> ostream& operator<<(ostream &os, const vector<T> &t) {
os<<"["; FOR(it,t) {if(it!=t.begin()) os<<","; os<<*it;} os<<"]"; return os;
}
template<class T> ostream& operator<<(ostream &os, const set<T> &t) {
os<<"{"; FOR(it,t) {if(it!=t.begin()) os<<","; os<<*it;} os<<"}"; return os;
}
template<class S, class T> ostream& operator<<(ostream &os, const pair<S,T> &t) { return os<<"("<<t.first<<","<<t.second<<")";}
template<class S, class T> pair<S,T> operator+(const pair<S,T> &s, const pair<S,T> &t){ return pair<S,T>(s.first+t.first, s.second+t.second);}
template<class S, class T> pair<S,T> operator-(const pair<S,T> &s, const pair<S,T> &t){ return pair<S,T>(s.first-t.first, s.second-t.second);}

struct UnionFind {
  vector<int> data;
  UnionFind(int size) : data(size, -1) { }
  bool unionSet(int x, int y) {
    x = root(x); y = root(y);
    if (x != y) {
      if (data[y] < data[x]) swap(x, y);
      data[x] += data[y]; data[y] = x;
    }
    return x != y;
  }
  bool findSet(int x, int y) {
    return root(x) == root(y);
  }
  int root(int x) {
    return data[x] < 0 ? x : data[x] = root(data[x]);
  }
  int size(int x) {
    return -data[root(x)];
  }
};


namespace geom{
#define X real()
#define Y imag()
#define at(i) ((*this)[i])
#define SELF (*this)
	enum {TRUE = 1, FALSE = 0, BORDER = -1};
	typedef int BOOL;
	typedef double R;
	const R INF = 1e8;
	R EPS = 1e-6;
	const R PI = 3.1415926535897932384626;
	inline int sig(const R &x) { return (abs(x) < EPS ? 0 : x > 0 ? 1 : -1); }
	inline BOOL less(const R &x, const R &y) {return sig(x-y) ? x < y : BORDER;}
	typedef complex<R> P;
	inline R norm(const P &p){return p.X*p.X+p.Y*p.Y;}
	inline R inp(const P& a, const P& b){return (conj(a)*b).X;}
	inline R outp(const P& a, const P& b){return (conj(a)*b).Y;}
	inline P unit(const P& p){return p/abs(p);}
	inline P proj(const P &s, const P &t){return t*inp(s, t)/norm(t);}
	inline int ccw(const P &s, const P &t, const P &p, int adv=0){
		int res = sig(outp(t-s, p-s));
		if(res || !adv) return res;
		if(sig(inp(t-s, p-s)) < 0) return -2;	// p-s-t
		if(sig(inp(s-t, p-t)) < 0) return 2;	// s-t-p
		return 0;								// s-p-t
	}
	
	
	struct L : public vector<P>{	// line
		L(const P &p1, const P &p2){this->push_back(p1);this->push_back(p2);}
		L(){}
		P dir()const {return at(1) - at(0);}
		BOOL online(const P &p)const {return !sig(outp(p-at(0), dir()));}
	};
	struct S : public L{	// segment
		S(const P &p1, const P &p2):L(p1, p2){}
		S(){}
		BOOL online(const P &p)const {
			if(!sig(norm(p - at(0))) || !sig(norm(p - at(1)))) return BORDER;
			return !sig(abs(at(0)-p) + abs(at(1) - p) - abs(at(0) - at(1)));
		}
	};
	struct C : public P{
		C(){}
		C(const P& p, const R r):P(p), r(r){}
		R r;
		BOOL inside(const P& p)const { return less(norm(p-SELF), r*r);}
	};
	struct F : public C{
		R s, t;
		F(const C &c, R ss, R tt):C(c), s(ss), t(tt){
			if(PI < s) s -= 2*PI;
			if(PI < t) t -= 2*PI;
		}
		BOOL inside(const P& p)const {
			P v = p - SELF;
			if(!sig(norm(v))) return BORDER;
			R a = arg(v);
			if(t < s){
				if((!less(s, a) && !less(a, t)) || !less(norm(v), r*r)) return FALSE;
				return less(s, a) | less(a, t) | less(norm(v), r*r);
			}else{
				if(!less(s, a) || !less(a, t) || !less(norm(v), r*r)) return FALSE;
				return less(s, a) | less(a, t) | less(norm(v), r*r);
			}
		}
	};
	P crosspoint(const L &l, const L &m);
	struct G : public vector<P>{
		G(size_type size=0):vector(size){}
		S edge(int i)const {return S(at(i), at(i+1 == size() ? 0 : i+1));}
		BOOL contains(const P &p)const {
			R sum = .0;
			REP(i, size()){
				if(S(at(i), at((i+1)%size())).online(p)) return BORDER;	// online
				sum += arg((at(i) - p) / (at((i+1)%size()) - p));
			}
			return !!sig(sum);
		}
		R area()const {
			R sum = 0;
			REP(i, size()) sum += outp(at(i), at((i+1)%size()));
			return abs(sum / 2.);
		}
		
		G convex_hull(bool online = false) {
			if(size() < 2) return *this;
			sort(ALL(*this));
			G r;
			r.resize((int)size()*2);
			int k=0;
			for(int i=0;i<size();r[k++]=at(i++))
				while(k>1 && ccw(r[k-2], r[k-1], at(i)) < 1-online) k--;
			int t = k;
			for(int i=(int)size()-1;i>=0;r[k++]=at(i--))
				while(k>t && ccw(r[k-2], r[k-1], at(i)) < 1-online) k--;
			r.resize(k-1);
			return r;
		}
		G cut(const L &l)const {
			G g;
			REP(i, size()){
				const S &s = edge(i);
				if(ccw(l[0], l[1], s[0], 0) >= 0) g.push_back(s[0]);
				if(ccw(l[0], l[1], s[0], 0) * ccw(l[0], l[1], s[1], 0) < 0)
					g.push_back(crosspoint(s, l));
			}
			return g;
		}
		G Voronoi(const vector<P> &p, const int t)const {
			G g = *this;
			REP(i, p.size())if(i!=t){
				const P m = (p[t]+p[i])*0.5;
				g = g.cut(L(m, m+(p[i]-p[t])*P(0, 1)));
			}
			return g;
		}
	};

	inline P proj(const P &s, const L &t){return t[0] + proj(s-t[0], t[1]-t[0]);}
	inline P reflect(const P &s, const L &t){return 2.*proj(s, t) - s;}
	inline S reflect(const S &s, const L &t){return S(reflect(s[0], t), reflect(s[1], t));}
	BOOL intersect(const S &s, const S &t){
		const int p = ccw(t[0], t[1], s[0], 1) * ccw(t[0], t[1], s[1], 1);
		const int q = ccw(s[0], s[1], t[0], 1) * ccw(s[0], s[1], t[1], 1);
		return (p>0||q>0) ? FALSE : (!p||!q) ? BORDER : TRUE;
	}
	BOOL intersect(const S &s, const L &l){
		if(l.online(s[0]) || l.online(s[1])) return BORDER;
		return (sig(outp(l.dir(), s[0]-l[0])) * sig(outp(l.dir(), s[1]-l[0])) <= 0);
	}
	R dist2(const L &l, const P &p){return norm(outp(l.dir(), p - l[0])) / norm(l.dir());}
	R dist2(const S &s, const P &p){
		if(inp(p-s[0],  s.dir()) < EPS) return norm(p - s[0]);
		if(inp(p-s[1], -s.dir()) < EPS) return norm(p - s[1]);
		return dist2((const L &)s, p);
	}
	R dist2(const S &s, const L &l){
		return intersect(s, l) ? .0 : min(dist2(l, s[0]), dist2(l, s[1]));
	}
	R dist2(const S &s, const S &t){
		return intersect(s, t) ? .0 : min(min(dist2(s, t[0]), dist2(t, s[0])), 
									   	  min(dist2(s, t[1]), dist2(t, s[1])));
	}
	template <class T> R dist2(const G &g, const T& t){ // todo: 内部に完全に含まれる場合
		R res = INF;
		REP(i, g.size()) res = min(res, dist2(g.edge(i), t));
		return res;
	}
	template<class S, class T> R dist(const S& s, const T& t){return sqrt(dist2(s, t));}
	inline BOOL intersect(const C &a, const C &b){
		return less((a.r-b.r)*(a.r-b.r), norm(a-b)) + less(norm(a-b), (a.r+b.r)*(a.r+b.r)) - 1;
	}
	inline BOOL intersect(const C &c, const L &l){
		return less(dist2(l, c), c.r*c.r);
	}
	inline BOOL intersect(const C &c, const S &s){
		int d = less(dist2(s, c), c.r*c.r);
		if(d != TRUE) return d;
		int p = c.inside(s[0]), q = c.inside(s[1]);
		return (p<0 || q<0) ? BORDER : p&q;
	}
	
	/*
	 * CCWでs[0]->s[1]にかけてが共通部分
	 */
	inline S crosspoint(const C &c1, const C &c2){
		if(!intersect(c1, c2)) return S();
		R d = abs(c1 - c2);
		R x = (c1.r*c1.r - c2.r*c2.r + d*d) / (2*d);
		R h = sqrt(max(0., c1.r*c1.r - x*x));
		P u = unit(c2-c1);
		return S(c1 + u*x + u*P(0,-1)*h, c1 + u*x + u*P(0,1)*h);
	}
	inline P crosspoint(const L &l, const L &m){
		R A = outp(l.dir(), m.dir()), B = outp(l.dir(), l[1] - m[0]);
		if(!sig(abs(A)) && !sig(abs(B))) return m[0]; // same line
		if(abs(A) < EPS) assert(false); // !!!PRECONDITION NOT SATISFIED!!!
		return m[0] + B / A * (m[1] - m[0]);
	}
	inline S crosspoint(const C &c, const L &l){
		R d2 = dist2(l, c);
		if(c.r*c.r+EPS < d2) return S();
		P m = proj(c, l);
		P u = unit(l[1]-l[0]);
		R d = sqrt(max(.0, c.r*c.r - d2));
		return S(m+u*d, m-u*d);
	}
	inline vector<P> crosspoint(const C &c, const S &s){
		vector<P> res = crosspoint(c, (const L&)s);
		RREP(i, res.size()){
			if(inp(res[i]-s[0], s.dir())*inp(res[i]-s[1], -s.dir())<EPS)
				res.erase(res.begin() + i);
		}
		return res;
	}
	inline R commonarea(const C &a, const C &b){
		if(less(norm(a-b), (a.r-b.r)*(a.r-b.r)) == TRUE) return min(a.r*a.r, b.r*b.r)*PI;
		if(less((a.r+b.r)*(a.r+b.r), norm(a-b)) == TRUE) return .0;
		double d = abs(a-b);
		double rc = (d*d + a.r*a.r - b.r*b.r) / (2*d);
		double theta = acos(rc / a.r);
		double phi = acos((d - rc) / b.r);
		return a.r*a.r*theta + b.r*b.r*phi - d*a.r*sin(theta);
	}
	vector<L> CommonTangent(C c1, C c2){
		if(c1.r > c2.r) swap(c1, c2);
		double d = abs(c1-c2);
		vector<L> res;
		if(d < EPS) return res;
		if(d + EPS > c1.r + c2.r){
			// 内接線
			P crs = (c1*c2.r + c2*c1.r) / (c1.r + c2.r);
			double rad = asin(c1.r/abs(crs-c1));
			res.push_back(L(crs, crs + (c1-crs)*polar(1., rad)));
			res.push_back(L(crs, crs + (c1-crs)*polar(1., -rad)));
		}
		if(c1.r + d + EPS > c2.r){
			// 外接線
			double rad = 0.5*PI+asin((c2.r-c1.r) / d);
			P v = unit(c2-c1)*polar(1., rad);
			if(c1.r + d - EPS < c2.r){
				res.push_back(L(c1+v*c1.r, c1+v*c1.r+(c1-c2)*P(0, 1)));
			}else{
				res.push_back(L(c1+v*c1.r, c2+v*c2.r));
				v = 2.*proj(v, c2-c1) - v;
				res.push_back(L(c1+v*c1.r, c2+v*c2.r));
			}
		}
		return res;
	}
	
	struct min_ball {
		P center;
		R radius2;
		min_ball(const vector<P>& p) {
			FOR(it, p) ps.push_back(*it);
		}
		min_ball& compile() {
			m = 0;
			center = P(0, 0);
			radius2 = -1;
			make_ball(ps.end());
			return *this;
		}
	private:
		list<P> ps;
		list<P>::iterator supp_end;
		int m;
		P v[3], c[3];
		R z[3], r[3];
		void pop() { --m; }
		void push(const P& p) {
			if (m == 0) {
				c[0] = p; r[0] = 0;
			} else {
				R e = norm(p-c[m-1]) - r[m-1];
				P delta = p - c[0];
				v[m] = p - c[0];
				for (int i = 1; i < m; ++i)
					v[m] -= v[i] * inp(v[i], delta) / z[i];
				z[m] = inp(v[m], v[m]);
				c[m] = c[m-1] + e*v[m]/z[m]*.5;
				r[m] = r[m-1] + e*e/z[m]*.25;
			}
			center	= c[m];
			radius2 = r[m]; ++m;
		}
		void make_ball(list<P>::iterator i) {
			supp_end = ps.begin();
			if (m == 3) return;
			for (list<P>::iterator k = ps.begin(); k != i; ) {
				list<P>::iterator j = k++;
				if (norm(*j-center) > radius2) {
					push(*j); make_ball(j); pop();
					move_to_front(j);
				}
			}
		}
		void move_to_front(list<P>::iterator j) {
			if (supp_end == j) ++supp_end;
			ps.splice (ps.begin(), ps, j);
		}
	};
	
	struct Arrangement{
		struct AEdge{
			int u, v, t;
			R cost;
			AEdge(int u=0, int v=0, int t=0, R cost=0)
				:u(u), v(v), t(t), cost(cost){}
		};
		typedef vector<vector<AEdge>> AGraph;
		vector<P> p;
		AGraph g;
		Arrangement(){}
		Arrangement(vector<S> seg){
			int m = seg.size();
			REP(i, m){
				p.push_back(seg[i][0]);
				p.push_back(seg[i][1]);
				REP(j, i) if(sig(outp(seg[i].dir(), seg[j].dir())) && intersect(seg[i], seg[j]) == TRUE)
					p.push_back(crosspoint(seg[i], seg[j]));
			}
			sort(ALL(p)); UNIQUE(p);
			int n=p.size();
			g.resize(n);
			REP(i, m){
				S &s = seg[i];
				vector<pair<R, int>> ps;
				REP(j, n) if(s.online(p[j])) ps.emplace_back(norm(p[j] - s[0]), j);
				sort(ALL(ps));
				REP(j, (int)ps.size()-1){
					const int u=ps[j].second;
					const int v=ps[j+1].second;
					g[u].emplace_back(u, v, 0, abs(p[u] - p[v]));
					g[v].emplace_back(v, u, 0, abs(p[u] - p[v]));
				}
			}
		}
		
		int getIdx(P q){
			auto it = lower_bound(ALL(p), q);
			if(it == p.end() || *it != q) return -1;
			return it - p.begin();
		}
	};

	struct DualGraph{
		struct DEdge{
			int u, v, f, l;
			R a;
			DEdge(int u, int v, R a):u(u),v(v),f(0),l(0){
				while(PI < a) a -= 2*PI;
				while(a < -PI) a += 2*PI;
				this->a = a;
			}
			bool operator==(const DEdge &opp) const{
				return v==opp.v;
			}
			bool operator<(const DEdge &opp) const{
				return a>opp.a;
			}
			bool operator<(const R &opp) const{
				return a>opp;
			}
			friend ostream& operator<<(ostream &os, const DEdge &t) { return os<<"("<<t.u<<","<<t.v<<","<<t.a*180/PI<<")";}
		};
		
		int n;
		vector<P> p;
		vector<vector<DEdge>> g;
		UnionFind uf;
		DualGraph(const vector<P> &p):p(p),g(p.size()),n(p.size()),uf(p.size()){}
		void add_edge(const int s, const int t){
			R a = arg(p[t]-p[s]);
			g[s].emplace_back(s, t, a);
			g[t].emplace_back(t, s, a > 0 ? a-PI : a+PI);
			uf.unionSet(s, t);
		}
		vector<G> poly;
		
		void add_polygon(int s, int t, R a){
			auto e = lower_bound(ALL(g[s]), a-EPS);
			if(e == g[s].end()) e = g[s].begin();
			if(e->f) return;
			e->f = 1;
			e->l = t;
			poly[t].push_back(p[s]);
			add_polygon(e->v, t, e->a > 0 ? e->a-PI : e->a+PI);
		}
		
		void toSpanningTree(){
			vector<pair<R, pii>> e;
			REP(i, n)REP(j, i)if(!uf.findSet(i, j))
				e.emplace_back(norm(p[i]-p[j]), pii(i, j));
			sort(ALL(e));
			REP(ii, e.size()){
				const int i = e[ii].second.first;
				const int j = e[ii].second.second;
				if(uf.findSet(i, j)) continue;
				const S s(p[i], p[j]);
				if([&](){
					REP(k, n)if(i!=k&&j!=k){
						FOR(it, g[k])
						if(intersect(s, S(p[k], p[it->v])) == TRUE) return 0;
					}
					return 1;
				}()) add_edge(i, j);
			}
		}
		
		vector<vi> dual(){
			toSpanningTree();
			
			REP(i, n){
				sort(ALL(g[i]));
				UNIQUE(g[i]);
			}
			int s = min_element(ALL(p)) - p.begin();
			poly.emplace_back();
			add_polygon(s, poly.size()-1, -PI*.5);
			REP(i, n)REP(j, g[i].size())if(!g[i][j].f){
				poly.emplace_back();
				add_polygon(i, poly.size()-1, g[i][j].a+2.*EPS);
			}
			int m = poly.size();
			vector<vi> dg(m);
			vector<unordered_map<int, int>> rev(n);
			REP(i, n)REP(j, g[i].size()){
				int u = i, v = g[i][j].v, l = g[i][j].l;
				if(u>v) swap(u, v);
				if(rev[u].find(v) != rev[u].end()){
					if(l != rev[u][v]){
						dg[l].push_back(rev[u][v]);
						dg[rev[u][v]].push_back(l);
					}
				}
				else rev[u][v] = l;
			}
			REP(i, m){
				sort(ALL(dg[i]));
				UNIQUE(dg[i]);
			}
			return dg;
		}
	};

#undef SELF
#undef at
}

using namespace geom;

int f = 0;
namespace std{
	bool operator<(const P &a, const P &b){return sig(a.X-b.X) ? a.X < b.X : a.Y+EPS < b.Y;}
	bool operator==(const P &a, const P &b){return abs(a-b) < EPS;}
	istream& operator>>(istream &is, P &p){R x,y;is>>x>>y;p=P(x, y);return is;}
	istream& operator>>(istream &is, L &l){l.resize(2);return is >> l[0] >> l[1];}
	istream& operator>>(istream &is, C &c){return is >> (P &)c >> c.r;}
	const double B = 500;
	const double Z = .2;
	ostream& operator<<(ostream &os, const C &c){return os << "circle("<<B+Z*(c.X)<<", "<<1000-B-Z*(c.Y)<<", "<<Z*(c.r)<<")";}
	ostream& operator<<(ostream &os, const P &p){return os << C(p, 2./Z);}
	ostream& operator<<(ostream &os, const S &s){return os << "line("<<B+Z*(s[0].X)<<", "<<1000-B-Z*(s[0].Y)<<", "<<B+Z*(s[1].X)<<", "<<1000-B-Z*(s[1].Y)<<")";}
	ostream& operator<<(ostream &os, const G &g){REP(i, g.size()) cout << g.edge(i) << endl;return os;}

}

bool bipartite_matching_dfs(
	int v, const vector< vector<int> > &conn,
	vector<bool> &used, vector<int> &match)
{
	used[v] = true;
	for(int i = 0; i < conn[v].size(); ++i){
		int u = conn[v][i], w = match[u];
		if(w < 0 || (!used[w] && bipartite_matching_dfs(w, conn, used, match))){
			match[v] = u;
			match[u] = v;
			return true;
		}
	}
	return false;
}
//O(E√V)
int bipartite_matching(const vector< vector<int> > &conn){
	int res = 0;
	vector<int> match(conn.size(), -1);
	vector<bool> used(conn.size(), false);
	for(int v = 0; v < conn.size(); ++v){
		if(match[v] < 0){
			fill(used.begin(), used.end(), false);
			if(bipartite_matching_dfs(v, conn, used, match)){ ++res; }
		}
	}
	return res;
}

int n, k;

int main(int argc, char *argv[]){
	ios::sync_with_stdio(false);
	cin >> n >> k;
	vector<C> c(n);
	REP(i, n) cin >> c[i];
	vector<R> x;
	map<P, int> idx;
	vector<unordered_set<int>> in;
	vector<P> p;
	REP(i, n){
		x.push_back(c[i].X - c[i].r);
		x.push_back(c[i].X);
		x.push_back(c[i].X + c[i].r);
		REP(j, i){
			S s = crosspoint(c[i], c[j]);
			if(s.size() == 2 && abs(s[0]-s[1]) < EPS) s.resize(1);
			FOR(it, s){
				if(idx.find(*it) == idx.end()){
					idx[*it] = p.size();
					p.push_back(*it);
					in.emplace_back();
				}
				in[idx[*it]].insert(i);
				in[idx[*it]].insert(j);
				x.push_back(it->X);
			}
			if(s.size() == 2 && abs(s[0]-s[1])>EPS){
				x.push_back((c[i] + unit((s[0]+s[1])*0.5 - c[i]) * c[i].r).X);
				x.push_back((c[j] + unit((s[0]+s[1])*0.5 - c[j]) * c[j].r).X);
			}
		}
	}
	sort(ALL(x));UNIQUE(x);
	REP(i, n){
		REP(j, x.size()){
			L l(P(x[j], 0.), P(x[j], 10.));
			S s = crosspoint(c[i], l);
			if(s.size() == 2 && norm(s[0]-s[1]) < EPS) s.resize(1);
			FOR(it, s){
				if(idx.find(*it) == idx.end()){
					idx[*it] = p.size();
					p.push_back(*it);
				}
			}
		}
	}
	in.resize(p.size());
	DualGraph dg(p);
	REP(i, n){
		vector<pair<R, int>> q;
		REP(j, p.size()){
			R d = abs(abs(p[j] - c[i]) - c[i].r);
			if(in[j].find(i)!=in[j].end() || [&](){
				REP(k, n)if(k!=i){
					if(abs(abs(p[j] - c[k]) - c[k].r) < d) return 0;
				}
				return 1;
			}()) q.emplace_back(arg(p[j] - c[i]), j);
		}
		sort(ALL(q));
		REP(j, (int)q.size()) dg.add_edge(q[j].second, q[(j+1)%q.size()].second);
	}
	EPS = 1e-8;
	vector<vi> g = dg.dual();
	if(k > 1) cout << dg.poly.size() - 1 << endl;
	else{
		REPS(i, (int)g.size()-1){
			g[i].erase(remove(ALL(g[i]), 0), g[i].end());
		}
		g[0].clear();
		cout << g.size() - bipartite_matching(g) - 1 << endl;
	}
	return 0;
}
accuracy: 1
time_ms: 580
memory_kb: 21624
final_rank: 7

code_snippet: #include <cstdio>
#include <cmath>
#include <cstring>
#include <cstdlib>
#include <climits>
#include <ctime>
#include <queue>
#include <stack>
#include <algorithm>
#include <list>
#include <vector>
#include <set>
#include <map>
#include <iostream>
#include <deque>
#include <complex>
#include <string>
#include <iomanip>
#include <sstream>
#include <bitset>
#include <valarray>
#include <unordered_map>
#include <iterator>
#include <assert.h>
using namespace std;
typedef long long int ll;
typedef unsigned int uint;
typedef unsigned char uchar;
typedef unsigned long long ull;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef vector<int> vi;

#define REP(i,x) for(int i=0;i<(int)(x);i++)
#define REPS(i,x) for(int i=1;i<=(int)(x);i++)
#define RREP(i,x) for(int i=((int)(x)-1);i>=0;i--)
#define RREPS(i,x) for(int i=((int)(x));i>0;i--)
#define FOR(i,c) for(__typeof((c).begin())i=(c).begin();i!=(c).end();i++)
#define RFOR(i,c) for(__typeof((c).rbegin())i=(c).rbegin();i!=(c).rend();i++)
#define ALL(container) (container).begin(), (container).end()
#define RALL(container) (container).rbegin(), (container).rend()
#define SZ(container) ((int)container.size())
#define mp(a,b) make_pair(a, b)
#define UNIQUE(v) v.erase( unique(v.begin(), v.end()), v.end() );

template<class T> bool chmax(T &a, const T &b) { if (a<b) { a=b; return 1; } return 0; }
template<class T> bool chmin(T &a, const T &b) { if (a>b) { a=b; return 1; } return 0; }
template<class T> ostream& operator<<(ostream &os, const vector<T> &t) {
os<<"["; FOR(it,t) {if(it!=t.begin()) os<<","; os<<*it;} os<<"]"; return os;
}
template<class T> ostream& operator<<(ostream &os, const set<T> &t) {
os<<"{"; FOR(it,t) {if(it!=t.begin()) os<<","; os<<*it;} os<<"}"; return os;
}
template<class S, class T> ostream& operator<<(ostream &os, const pair<S,T> &t) { return os<<"("<<t.first<<","<<t.second<<")";}
template<class S, class T> pair<S,T> operator+(const pair<S,T> &s, const pair<S,T> &t){ return pair<S,T>(s.first+t.first, s.second+t.second);}
template<class S, class T> pair<S,T> operator-(const pair<S,T> &s, const pair<S,T> &t){ return pair<S,T>(s.first-t.first, s.second-t.second);}

struct UnionFind {
  vector<int> data;
  UnionFind(int size) : data(size, -1) { }
  bool unionSet(int x, int y) {
    x = root(x); y = root(y);
    if (x != y) {
      if (data[y] < data[x]) swap(x, y);
      data[x] += data[y]; data[y] = x;
    }
    return x != y;
  }
  bool findSet(int x, int y) {
    return root(x) == root(y);
  }
  int root(int x) {
    return data[x] < 0 ? x : data[x] = root(data[x]);
  }
  int size(int x) {
    return -data[root(x)];
  }
};


namespace geom{
#define X real()
#define Y imag()
#define at(i) ((*this)[i])
#define SELF (*this)
	enum {TRUE = 1, FALSE = 0, BORDER = -1};
	typedef int BOOL;
	typedef double R;
	const R INF = 1e8;
	R EPS = 1e-6;
	const R PI = 3.1415926535897932384626;
	inline int sig(const R &x) { return (abs(x) < EPS ? 0 : x > 0 ? 1 : -1); }
	inline BOOL less(const R &x, const R &y) {return sig(x-y) ? x < y : BORDER;}
	typedef complex<R> P;
	inline R norm(const P &p){return p.X*p.X+p.Y*p.Y;}
	inline R inp(const P& a, const P& b){return (conj(a)*b).X;}
	inline R outp(const P& a, const P& b){return (conj(a)*b).Y;}
	inline P unit(const P& p){return p/abs(p);}
	inline P proj(const P &s, const P &t){return t*inp(s, t)/norm(t);}
	inline int ccw(const P &s, const P &t, const P &p, int adv=0){
		int res = sig(outp(t-s, p-s));
		if(res || !adv) return res;
		if(sig(inp(t-s, p-s)) < 0) return -2;	// p-s-t
		if(sig(inp(s-t, p-t)) < 0) return 2;	// s-t-p
		return 0;								// s-p-t
	}
	
	
	struct L : public vector<P>{	// line
		L(const P &p1, const P &p2){this->push_back(p1);this->push_back(p2);}
		L(){}
		P dir()const {return at(1) - at(0);}
		BOOL online(const P &p)const {return !sig(outp(p-at(0), dir()));}
	};
	struct S : public L{	// segment
		S(const P &p1, const P &p2):L(p1, p2){}
		S(){}
		BOOL online(const P &p)const {
			if(!sig(norm(p - at(0))) || !sig(norm(p - at(1)))) return BORDER;
			return !sig(abs(at(0)-p) + abs(at(1) - p) - abs(at(0) - at(1)));
		}
	};
	struct C : public P{
		C(){}
		C(const P& p, const R r):P(p), r(r){}
		R r;
		BOOL inside(const P& p)const { return less(norm(p-SELF), r*r);}
	};
	struct F : public C{
		R s, t;
		F(const C &c, R ss, R tt):C(c), s(ss), t(tt){
			if(PI < s) s -= 2*PI;
			if(PI < t) t -= 2*PI;
		}
		BOOL inside(const P& p)const {
			P v = p - SELF;
			if(!sig(norm(v))) return BORDER;
			R a = arg(v);
			if(t < s){
				if((!less(s, a) && !less(a, t)) || !less(norm(v), r*r)) return FALSE;
				return less(s, a) | less(a, t) | less(norm(v), r*r);
			}else{
				if(!less(s, a) || !less(a, t) || !less(norm(v), r*r)) return FALSE;
				return less(s, a) | less(a, t) | less(norm(v), r*r);
			}
		}
	};
	P crosspoint(const L &l, const L &m);
	struct G : public vector<P>{
		G(size_type size=0):vector(size){}
		S edge(int i)const {return S(at(i), at(i+1 == size() ? 0 : i+1));}
		BOOL contains(const P &p)const {
			R sum = .0;
			REP(i, size()){
				if(S(at(i), at((i+1)%size())).online(p)) return BORDER;	// online
				sum += arg((at(i) - p) / (at((i+1)%size()) - p));
			}
			return !!sig(sum);
		}
		R area()const {
			R sum = 0;
			REP(i, size()) sum += outp(at(i), at((i+1)%size()));
			return abs(sum / 2.);
		}
		
		G convex_hull(bool online = false) {
			if(size() < 2) return *this;
			sort(ALL(*this));
			G r;
			r.resize((int)size()*2);
			int k=0;
			for(int i=0;i<size();r[k++]=at(i++))
				while(k>1 && ccw(r[k-2], r[k-1], at(i)) < 1-online) k--;
			int t = k;
			for(int i=(int)size()-1;i>=0;r[k++]=at(i--))
				while(k>t && ccw(r[k-2], r[k-1], at(i)) < 1-online) k--;
			r.resize(k-1);
			return r;
		}
		G cut(const L &l)const {
			G g;
			REP(i, size()){
				const S &s = edge(i);
				if(ccw(l[0], l[1], s[0], 0) >= 0) g.push_back(s[0]);
				if(ccw(l[0], l[1], s[0], 0) * ccw(l[0], l[1], s[1], 0) < 0)
					g.push_back(crosspoint(s, l));
			}
			return g;
		}
		G Voronoi(const vector<P> &p, const int t)const {
			G g = *this;
			REP(i, p.size())if(i!=t){
				const P m = (p[t]+p[i])*0.5;
				g = g.cut(L(m, m+(p[i]-p[t])*P(0, 1)));
			}
			return g;
		}
	};

	inline P proj(const P &s, const L &t){return t[0] + proj(s-t[0], t[1]-t[0]);}
	inline P reflect(const P &s, const L &t){return 2.*proj(s, t) - s;}
	inline S reflect(const S &s, const L &t){return S(reflect(s[0], t), reflect(s[1], t));}
	BOOL intersect(const S &s, const S &t){
		const int p = ccw(t[0], t[1], s[0], 1) * ccw(t[0], t[1], s[1], 1);
		const int q = ccw(s[0], s[1], t[0], 1) * ccw(s[0], s[1], t[1], 1);
		return (p>0||q>0) ? FALSE : (!p||!q) ? BORDER : TRUE;
	}
	BOOL intersect(const S &s, const L &l){
		if(l.online(s[0]) || l.online(s[1])) return BORDER;
		return (sig(outp(l.dir(), s[0]-l[0])) * sig(outp(l.dir(), s[1]-l[0])) <= 0);
	}
	R dist2(const L &l, const P &p){return norm(outp(l.dir(), p - l[0])) / norm(l.dir());}
	R dist2(const S &s, const P &p){
		if(inp(p-s[0],  s.dir()) < EPS) return norm(p - s[0]);
		if(inp(p-s[1], -s.dir()) < EPS) return norm(p - s[1]);
		return dist2((const L &)s, p);
	}
	R dist2(const S &s, const L &l){
		return intersect(s, l) ? .0 : min(dist2(l, s[0]), dist2(l, s[1]));
	}
	R dist2(const S &s, const S &t){
		return intersect(s, t) ? .0 : min(min(dist2(s, t[0]), dist2(t, s[0])), 
									   	  min(dist2(s, t[1]), dist2(t, s[1])));
	}
	template <class T> R dist2(const G &g, const T& t){ // todo: 内部に完全に含まれる場合
		R res = INF;
		REP(i, g.size()) res = min(res, dist2(g.edge(i), t));
		return res;
	}
	template<class S, class T> R dist(const S& s, const T& t){return sqrt(dist2(s, t));}
	inline BOOL intersect(const C &a, const C &b){
		return less((a.r-b.r)*(a.r-b.r), norm(a-b)) + less(norm(a-b), (a.r+b.r)*(a.r+b.r)) - 1;
	}
	inline BOOL intersect(const C &c, const L &l){
		return less(dist2(l, c), c.r*c.r);
	}
	inline BOOL intersect(const C &c, const S &s){
		int d = less(dist2(s, c), c.r*c.r);
		if(d != TRUE) return d;
		int p = c.inside(s[0]), q = c.inside(s[1]);
		return (p<0 || q<0) ? BORDER : p&q;
	}
	
	/*
	 * CCWでs[0]->s[1]にかけてが共通部分
	 */
	inline S crosspoint(const C &c1, const C &c2){
		if(!intersect(c1, c2)) return S();
		R d = abs(c1 - c2);
		R x = (c1.r*c1.r - c2.r*c2.r + d*d) / (2*d);
		R h = sqrt(max(0., c1.r*c1.r - x*x));
		P u = unit(c2-c1);
		return S(c1 + u*x + u*P(0,-1)*h, c1 + u*x + u*P(0,1)*h);
	}
	inline P crosspoint(const L &l, const L &m){
		R A = outp(l.dir(), m.dir()), B = outp(l.dir(), l[1] - m[0]);
		if(!sig(abs(A)) && !sig(abs(B))) return m[0]; // same line
		if(abs(A) < EPS) assert(false); // !!!PRECONDITION NOT SATISFIED!!!
		return m[0] + B / A * (m[1] - m[0]);
	}
	inline S crosspoint(const C &c, const L &l){
		R d2 = dist2(l, c);
		if(c.r*c.r+EPS < d2) return S();
		P m = proj(c, l);
		P u = unit(l[1]-l[0]);
		R d = sqrt(max(.0, c.r*c.r - d2));
		return S(m+u*d, m-u*d);
	}
	inline vector<P> crosspoint(const C &c, const S &s){
		vector<P> res = crosspoint(c, (const L&)s);
		RREP(i, res.size()){
			if(inp(res[i]-s[0], s.dir())*inp(res[i]-s[1], -s.dir())<EPS)
				res.erase(res.begin() + i);
		}
		return res;
	}
	inline R commonarea(const C &a, const C &b){
		if(less(norm(a-b), (a.r-b.r)*(a.r-b.r)) == TRUE) return min(a.r*a.r, b.r*b.r)*PI;
		if(less((a.r+b.r)*(a.r+b.r), norm(a-b)) == TRUE) return .0;
		double d = abs(a-b);
		double rc = (d*d + a.r*a.r - b.r*b.r) / (2*d);
		double theta = acos(rc / a.r);
		double phi = acos((d - rc) / b.r);
		return a.r*a.r*theta + b.r*b.r*phi - d*a.r*sin(theta);
	}
	vector<L> CommonTangent(C c1, C c2){
		if(c1.r > c2.r) swap(c1, c2);
		double d = abs(c1-c2);
		vector<L> res;
		if(d < EPS) return res;
		if(d + EPS > c1.r + c2.r){
			// 内接線
			P crs = (c1*c2.r + c2*c1.r) / (c1.r + c2.r);
			double rad = asin(c1.r/abs(crs-c1));
			res.push_back(L(crs, crs + (c1-crs)*polar(1., rad)));
			res.push_back(L(crs, crs + (c1-crs)*polar(1., -rad)));
		}
		if(c1.r + d + EPS > c2.r){
			// 外接線
			double rad = 0.5*PI+asin((c2.r-c1.r) / d);
			P v = unit(c2-c1)*polar(1., rad);
			if(c1.r + d - EPS < c2.r){
				res.push_back(L(c1+v*c1.r, c1+v*c1.r+(c1-c2)*P(0, 1)));
			}else{
				res.push_back(L(c1+v*c1.r, c2+v*c2.r));
				v = 2.*proj(v, c2-c1) - v;
				res.push_back(L(c1+v*c1.r, c2+v*c2.r));
			}
		}
		return res;
	}
	
	struct min_ball {
		P center;
		R radius2;
		min_ball(const vector<P>& p) {
			FOR(it, p) ps.push_back(*it);
		}
		min_ball& compile() {
			m = 0;
			center = P(0, 0);
			radius2 = -1;
			make_ball(ps.end());
			return *this;
		}
	private:
		list<P> ps;
		list<P>::iterator supp_end;
		int m;
		P v[3], c[3];
		R z[3], r[3];
		void pop() { --m; }
		void push(const P& p) {
			if (m == 0) {
				c[0] = p; r[0] = 0;
			} else {
				R e = norm(p-c[m-1]) - r[m-1];
				P delta = p - c[0];
				v[m] = p - c[0];
				for (int i = 1; i < m; ++i)
					v[m] -= v[i] * inp(v[i], delta) / z[i];
				z[m] = inp(v[m], v[m]);
				c[m] = c[m-1] + e*v[m]/z[m]*.5;
				r[m] = r[m-1] + e*e/z[m]*.25;
			}
			center	= c[m];
			radius2 = r[m]; ++m;
		}
		void make_ball(list<P>::iterator i) {
			supp_end = ps.begin();
			if (m == 3) return;
			for (list<P>::iterator k = ps.begin(); k != i; ) {
				list<P>::iterator j = k++;
				if (norm(*j-center) > radius2) {
					push(*j); make_ball(j); pop();
					move_to_front(j);
				}
			}
		}
		void move_to_front(list<P>::iterator j) {
			if (supp_end == j) ++supp_end;
			ps.splice (ps.begin(), ps, j);
		}
	};
	
	struct Arrangement{
		struct AEdge{
			int u, v, t;
			R cost;
			AEdge(int u=0, int v=0, int t=0, R cost=0)
				:u(u), v(v), t(t), cost(cost){}
		};
		typedef vector<vector<AEdge>> AGraph;
		vector<P> p;
		AGraph g;
		Arrangement(){}
		Arrangement(vector<S> seg){
			int m = seg.size();
			REP(i, m){
				p.push_back(seg[i][0]);
				p.push_back(seg[i][1]);
				REP(j, i) if(sig(outp(seg[i].dir(), seg[j].dir())) && intersect(seg[i], seg[j]) == TRUE)
					p.push_back(crosspoint(seg[i], seg[j]));
			}
			sort(ALL(p)); UNIQUE(p);
			int n=p.size();
			g.resize(n);
			REP(i, m){
				S &s = seg[i];
				vector<pair<R, int>> ps;
				REP(j, n) if(s.online(p[j])) ps.emplace_back(norm(p[j] - s[0]), j);
				sort(ALL(ps));
				REP(j, (int)ps.size()-1){
					const int u=ps[j].second;
					const int v=ps[j+1].second;
					g[u].emplace_back(u, v, 0, abs(p[u] - p[v]));
					g[v].emplace_back(v, u, 0, abs(p[u] - p[v]));
				}
			}
		}
		
		int getIdx(P q){
			auto it = lower_bound(ALL(p), q);
			if(it == p.end() || *it != q) return -1;
			return it - p.begin();
		}
	};

	struct DualGraph{
		struct DEdge{
			int u, v, f, l;
			R a;
			DEdge(int u, int v, R a):u(u),v(v),f(0),l(0){
				while(PI < a) a -= 2*PI;
				while(a < -PI) a += 2*PI;
				this->a = a;
			}
			bool operator==(const DEdge &opp) const{
				return v==opp.v;
			}
			bool operator<(const DEdge &opp) const{
				return a>opp.a;
			}
			bool operator<(const R &opp) const{
				return a>opp;
			}
			friend ostream& operator<<(ostream &os, const DEdge &t) { return os<<"("<<t.u<<","<<t.v<<","<<t.a*180/PI<<")";}
		};
		
		int n;
		vector<P> p;
		vector<vector<DEdge>> g;
		UnionFind uf;
		DualGraph(const vector<P> &p):p(p),g(p.size()),n(p.size()),uf(p.size()){}
		void add_edge(const int s, const int t){
			R a = arg(p[t]-p[s]);
			g[s].emplace_back(s, t, a);
			g[t].emplace_back(t, s, a > 0 ? a-PI : a+PI);
			uf.unionSet(s, t);
		}
		vector<G> poly;
		
		void add_polygon(int s, int t, R a){
			auto e = lower_bound(ALL(g[s]), a-EPS);
			if(e == g[s].end()) e = g[s].begin();
			if(e->f) return;
			e->f = 1;
			e->l = t;
			poly[t].push_back(p[s]);
			add_polygon(e->v, t, e->a > 0 ? e->a-PI : e->a+PI);
		}
		
		void toSpanningTree(){
			vector<pair<R, pii>> e;
			REP(i, n)REP(j, i)if(!uf.findSet(i, j))
				e.emplace_back(norm(p[i]-p[j]), pii(i, j));
			sort(ALL(e));
			REP(ii, e.size()){
				const int i = e[ii].second.first;
				const int j = e[ii].second.second;
				if(uf.findSet(i, j)) continue;
				const S s(p[i], p[j]);
				if([&](){
					REP(k, n)if(i!=k&&j!=k){
						FOR(it, g[k])
						if(intersect(s, S(p[k], p[it->v])) == TRUE) return 0;
					}
					return 1;
				}()) add_edge(i, j);
			}
		}
		
		vector<vi> dual(){
			toSpanningTree();
			
			REP(i, n){
				sort(ALL(g[i]));
				UNIQUE(g[i]);
			}
			int s = min_element(ALL(p)) - p.begin();
			poly.emplace_back();
			add_polygon(s, poly.size()-1, -PI*.5);
			REP(i, n)REP(j, g[i].size())if(!g[i][j].f){
				poly.emplace_back();
				add_polygon(i, poly.size()-1, g[i][j].a+2.*EPS);
			}
			int m = poly.size();
			vector<vi> dg(m);
			vector<unordered_map<int, int>> rev(n);
			REP(i, n)REP(j, g[i].size()){
				int u = i, v = g[i][j].v, l = g[i][j].l;
				if(u>v) swap(u, v);
				if(rev[u].find(v) != rev[u].end()){
					if(l != rev[u][v]){
						dg[l].push_back(rev[u][v]);
						dg[rev[u][v]].push_back(l);
					}
				}
				else rev[u][v] = l;
			}
			REP(i, m){
				sort(ALL(dg[i]));
				UNIQUE(dg[i]);
			}
			return dg;
		}
	};

#undef SELF
#undef at
}

using namespace geom;

int f = 0;
namespace std{
	bool operator<(const P &a, const P &b){return sig(a.X-b.X) ? a.X < b.X : a.Y+EPS < b.Y;}
	bool operator==(const P &a, const P &b){return abs(a-b) < EPS;}
	istream& operator>>(istream &is, P &p){R x,y;is>>x>>y;p=P(x, y);return is;}
	istream& operator>>(istream &is, L &l){l.resize(2);return is >> l[0] >> l[1];}
	istream& operator>>(istream &is, C &c){return is >> (P &)c >> c.r;}
	const double B = 500;
	const double Z = .2;
	ostream& operator<<(ostream &os, const C &c){return os << "circle("<<B+Z*(c.X)<<", "<<1000-B-Z*(c.Y)<<", "<<Z*(c.r)<<")";}
	ostream& operator<<(ostream &os, const P &p){return os << C(p, 2./Z);}
	ostream& operator<<(ostream &os, const S &s){return os << "line("<<B+Z*(s[0].X)<<", "<<1000-B-Z*(s[0].Y)<<", "<<B+Z*(s[1].X)<<", "<<1000-B-Z*(s[1].Y)<<")";}
	ostream& operator<<(ostream &os, const G &g){REP(i, g.size()) cout << g.edge(i) << endl;return os;}

}

bool bipartite_matching_dfs(
	int v, const vector< vector<int> > &conn,
	vector<bool> &used, vector<int> &match)
{
	used[v] = true;
	for(int i = 0; i < conn[v].size(); ++i){
		int u = conn[v][i], w = match[u];
		if(w < 0 || (!used[w] && bipartite_matching_dfs(w, conn, used, match))){
			match[v] = u;
			match[u] = v;
			return true;
		}
	}
	return false;
}
//O(E√V)
int bipartite_matching(const vector< vector<int> > &conn){
	int res = 0;
	vector<int> match(conn.size(), -1);
	vector<bool> used(conn.size(), false);
	for(int v = 0; v < conn.size(); ++v){
		if(match[v] < 0){
			fill(used.begin(), used.end(), false);
			if(bipartite_matching_dfs(v, conn, used, match)){ ++res; }
		}
	}
	return res;
}

int n, k;

int main(int argc, char *argv[]){
	ios::sync_with_stdio(false);
	cin >> n >> k;
	vector<C> c(n);
	REP(i, n){
		cin >> c[i];
//		c[i] *= polar(1., 0);
	}
	vector<R> x;
	map<P, int> idx;
	vector<vi> in(10000);
	vector<P> p;
	REP(i, n){
		x.push_back(c[i].X - c[i].r);
		x.push_back(c[i].X);
		x.push_back(c[i].X + c[i].r);
		REP(j, i){
			S s = crosspoint(c[i], c[j]);
			if(s.size() == 2 && abs(s[0]-s[1]) < EPS) s.resize(1);
			FOR(it, s){
				if(idx.find(*it) == idx.end()){
					idx[*it] = p.size();
					p.push_back(*it);
				}
				in[idx[*it]].push_back(i);
				in[idx[*it]].push_back(j);
				x.push_back(it->X);
			}
			if(s.size() == 2 && abs(s[0]-s[1])>EPS){
				x.push_back((c[i] + unit((s[0]+s[1])*0.5 - c[i]) * c[i].r).X);
				x.push_back((c[j] + unit((s[0]+s[1])*0.5 - c[j]) * c[j].r).X);
			}
		}
	}
	sort(ALL(x));UNIQUE(x);
//cerr << x << endl;
	REP(i, n){
		REP(j, x.size()){
			L l(P(x[j], 0.), P(x[j], 10.));
			S s = crosspoint(c[i], l);
			if(s.size() == 2 && abs(s[0]-s[1]) < EPS) s.resize(1);
			FOR(it, s){
				if(idx.find(*it) == idx.end()){
					idx[*it] = p.size();
					p.push_back(*it);
				}
			}
		}
	}
	in.resize(p.size());
//		cerr << in << endl;
//	sort(ALL(p));
//cerr << p << endl << endl;
//	UNIQUE(p);
//FOR(it, p)cout << *it << endl;
//cerr << "p enum" << endl;
	DualGraph dg(p);
	REP(i, n){
		vector<pair<R, int>> q;
		REP(j, p.size()){
			R d = abs(abs(p[j] - c[i]) - c[i].r);
			if(count(ALL(in[j]), i) || (!sig(abs(p[j] - c[i]) - c[i].r) && [&](){
				REP(k, n)if(k!=i){
					if(abs(abs(p[j] - c[k]) - c[k].r) < d) return 0;
				}
				return 1;
			}())) q.emplace_back(arg(p[j] - c[i]), j);
		}
		sort(ALL(q));
//		cerr << q << endl;
		REP(j, (int)q.size()) dg.add_edge(q[j].second, q[(j+1)%q.size()].second);
	}
	EPS = 1e-8;
//cerr << "edge" << endl;
	vector<vi> g = dg.dual();
//cerr << "dual" << endl;
//FOR(it, c) cout << *it << endl;
//if(argc == 1) FOR(it, dg.poly) if(it != dg.poly.begin())cout << *it << endl;
//else cout << dg.poly[atoi(argv[1])] << endl;
	if(k > 1) cout << dg.poly.size() - 1 << endl;
	else{
		REPS(i, (int)g.size()-1){
			g[i].erase(remove(ALL(g[i]), 0), g[i].end());
		}
		g[0].clear();
//		cerr << g << endl;
		cout << g.size() - bipartite_matching(g) - 1 << endl;
	}
	return 0;
}
accuracy: 1
time_ms: 590
memory_kb: 19776
final_rank: 6

code_snippet: #include <cstdio>
#include <cmath>
#include <cstring>
#include <cstdlib>
#include <climits>
#include <ctime>
#include <queue>
#include <stack>
#include <algorithm>
#include <list>
#include <vector>
#include <set>
#include <map>
#include <iostream>
#include <deque>
#include <complex>
#include <string>
#include <iomanip>
#include <sstream>
#include <bitset>
#include <valarray>
#include <unordered_map>
#include <iterator>
#include <assert.h>
using namespace std;
typedef long long int ll;
typedef unsigned int uint;
typedef unsigned char uchar;
typedef unsigned long long ull;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef vector<int> vi;

#define REP(i,x) for(int i=0;i<(int)(x);i++)
#define REPS(i,x) for(int i=1;i<=(int)(x);i++)
#define RREP(i,x) for(int i=((int)(x)-1);i>=0;i--)
#define RREPS(i,x) for(int i=((int)(x));i>0;i--)
#define FOR(i,c) for(__typeof((c).begin())i=(c).begin();i!=(c).end();i++)
#define RFOR(i,c) for(__typeof((c).rbegin())i=(c).rbegin();i!=(c).rend();i++)
#define ALL(container) (container).begin(), (container).end()
#define RALL(container) (container).rbegin(), (container).rend()
#define SZ(container) ((int)container.size())
#define mp(a,b) make_pair(a, b)
#define UNIQUE(v) v.erase( unique(v.begin(), v.end()), v.end() );

template<class T> bool chmax(T &a, const T &b) { if (a<b) { a=b; return 1; } return 0; }
template<class T> bool chmin(T &a, const T &b) { if (a>b) { a=b; return 1; } return 0; }
template<class T> ostream& operator<<(ostream &os, const vector<T> &t) {
os<<"["; FOR(it,t) {if(it!=t.begin()) os<<","; os<<*it;} os<<"]"; return os;
}
template<class T> ostream& operator<<(ostream &os, const set<T> &t) {
os<<"{"; FOR(it,t) {if(it!=t.begin()) os<<","; os<<*it;} os<<"}"; return os;
}
template<class S, class T> ostream& operator<<(ostream &os, const pair<S,T> &t) { return os<<"("<<t.first<<","<<t.second<<")";}
template<class S, class T> pair<S,T> operator+(const pair<S,T> &s, const pair<S,T> &t){ return pair<S,T>(s.first+t.first, s.second+t.second);}
template<class S, class T> pair<S,T> operator-(const pair<S,T> &s, const pair<S,T> &t){ return pair<S,T>(s.first-t.first, s.second-t.second);}

struct UnionFind {
  vector<int> data;
  UnionFind(int size) : data(size, -1) { }
  bool unionSet(int x, int y) {
    x = root(x); y = root(y);
    if (x != y) {
      if (data[y] < data[x]) swap(x, y);
      data[x] += data[y]; data[y] = x;
    }
    return x != y;
  }
  bool findSet(int x, int y) {
    return root(x) == root(y);
  }
  int root(int x) {
    return data[x] < 0 ? x : data[x] = root(data[x]);
  }
  int size(int x) {
    return -data[root(x)];
  }
};


namespace geom{
#define X real()
#define Y imag()
#define at(i) ((*this)[i])
#define SELF (*this)
	enum {TRUE = 1, FALSE = 0, BORDER = -1};
	typedef int BOOL;
	typedef double R;
	const R INF = 1e8;
	R EPS = 1e-6;
	const R PI = 3.1415926535897932384626;
	inline int sig(const R &x) { return (abs(x) < EPS ? 0 : x > 0 ? 1 : -1); }
	inline BOOL less(const R &x, const R &y) {return sig(x-y) ? x < y : BORDER;}
	typedef complex<R> P;
	inline R norm(const P &p){return p.X*p.X+p.Y*p.Y;}
	inline R inp(const P& a, const P& b){return (conj(a)*b).X;}
	inline R outp(const P& a, const P& b){return (conj(a)*b).Y;}
	inline P unit(const P& p){return p/abs(p);}
	inline P proj(const P &s, const P &t){return t*inp(s, t)/norm(t);}
	inline int ccw(const P &s, const P &t, const P &p, int adv=0){
		int res = sig(outp(t-s, p-s));
		if(res || !adv) return res;
		if(sig(inp(t-s, p-s)) < 0) return -2;	// p-s-t
		if(sig(inp(s-t, p-t)) < 0) return 2;	// s-t-p
		return 0;								// s-p-t
	}
	
	
	struct L : public vector<P>{	// line
		L(const P &p1, const P &p2){this->push_back(p1);this->push_back(p2);}
		L(){}
		P dir()const {return at(1) - at(0);}
		BOOL online(const P &p)const {return !sig(outp(p-at(0), dir()));}
	};
	struct S : public L{	// segment
		S(const P &p1, const P &p2):L(p1, p2){}
		S(){}
		BOOL online(const P &p)const {
			if(!sig(norm(p - at(0))) || !sig(norm(p - at(1)))) return BORDER;
			return !sig(abs(at(0)-p) + abs(at(1) - p) - abs(at(0) - at(1)));
		}
	};
	struct C : public P{
		C(){}
		C(const P& p, const R r):P(p), r(r){}
		R r;
		BOOL inside(const P& p)const { return less(norm(p-SELF), r*r);}
	};
	struct F : public C{
		R s, t;
		F(const C &c, R ss, R tt):C(c), s(ss), t(tt){
			if(PI < s) s -= 2*PI;
			if(PI < t) t -= 2*PI;
		}
		BOOL inside(const P& p)const {
			P v = p - SELF;
			if(!sig(norm(v))) return BORDER;
			R a = arg(v);
			if(t < s){
				if((!less(s, a) && !less(a, t)) || !less(norm(v), r*r)) return FALSE;
				return less(s, a) | less(a, t) | less(norm(v), r*r);
			}else{
				if(!less(s, a) || !less(a, t) || !less(norm(v), r*r)) return FALSE;
				return less(s, a) | less(a, t) | less(norm(v), r*r);
			}
		}
	};
	P crosspoint(const L &l, const L &m);
	struct G : public vector<P>{
		G(size_type size=0):vector(size){}
		S edge(int i)const {return S(at(i), at(i+1 == size() ? 0 : i+1));}
		BOOL contains(const P &p)const {
			R sum = .0;
			REP(i, size()){
				if(S(at(i), at((i+1)%size())).online(p)) return BORDER;	// online
				sum += arg((at(i) - p) / (at((i+1)%size()) - p));
			}
			return !!sig(sum);
		}
		R area()const {
			R sum = 0;
			REP(i, size()) sum += outp(at(i), at((i+1)%size()));
			return abs(sum / 2.);
		}
		
		G convex_hull(bool online = false) {
			if(size() < 2) return *this;
			sort(ALL(*this));
			G r;
			r.resize((int)size()*2);
			int k=0;
			for(int i=0;i<size();r[k++]=at(i++))
				while(k>1 && ccw(r[k-2], r[k-1], at(i)) < 1-online) k--;
			int t = k;
			for(int i=(int)size()-1;i>=0;r[k++]=at(i--))
				while(k>t && ccw(r[k-2], r[k-1], at(i)) < 1-online) k--;
			r.resize(k-1);
			return r;
		}
		G cut(const L &l)const {
			G g;
			REP(i, size()){
				const S &s = edge(i);
				if(ccw(l[0], l[1], s[0], 0) >= 0) g.push_back(s[0]);
				if(ccw(l[0], l[1], s[0], 0) * ccw(l[0], l[1], s[1], 0) < 0)
					g.push_back(crosspoint(s, l));
			}
			return g;
		}
		G Voronoi(const vector<P> &p, const int t)const {
			G g = *this;
			REP(i, p.size())if(i!=t){
				const P m = (p[t]+p[i])*0.5;
				g = g.cut(L(m, m+(p[i]-p[t])*P(0, 1)));
			}
			return g;
		}
	};

	inline P proj(const P &s, const L &t){return t[0] + proj(s-t[0], t[1]-t[0]);}
	inline P reflect(const P &s, const L &t){return 2.*proj(s, t) - s;}
	inline S reflect(const S &s, const L &t){return S(reflect(s[0], t), reflect(s[1], t));}
	BOOL intersect(const S &s, const S &t){
		const int p = ccw(t[0], t[1], s[0], 1) * ccw(t[0], t[1], s[1], 1);
		const int q = ccw(s[0], s[1], t[0], 1) * ccw(s[0], s[1], t[1], 1);
		return (p>0||q>0) ? FALSE : (!p||!q) ? BORDER : TRUE;
	}
	BOOL intersect(const S &s, const L &l){
		if(l.online(s[0]) || l.online(s[1])) return BORDER;
		return (sig(outp(l.dir(), s[0]-l[0])) * sig(outp(l.dir(), s[1]-l[0])) <= 0);
	}
	R dist2(const L &l, const P &p){return norm(outp(l.dir(), p - l[0])) / norm(l.dir());}
	R dist2(const S &s, const P &p){
		if(inp(p-s[0],  s.dir()) < EPS) return norm(p - s[0]);
		if(inp(p-s[1], -s.dir()) < EPS) return norm(p - s[1]);
		return dist2((const L &)s, p);
	}
	R dist2(const S &s, const L &l){
		return intersect(s, l) ? .0 : min(dist2(l, s[0]), dist2(l, s[1]));
	}
	R dist2(const S &s, const S &t){
		return intersect(s, t) ? .0 : min(min(dist2(s, t[0]), dist2(t, s[0])), 
									   	  min(dist2(s, t[1]), dist2(t, s[1])));
	}
	template <class T> R dist2(const G &g, const T& t){ // todo: 内部に完全に含まれる場合
		R res = INF;
		REP(i, g.size()) res = min(res, dist2(g.edge(i), t));
		return res;
	}
	template<class S, class T> R dist(const S& s, const T& t){return sqrt(dist2(s, t));}
	inline BOOL intersect(const C &a, const C &b){
		return less((a.r-b.r)*(a.r-b.r), norm(a-b)) + less(norm(a-b), (a.r+b.r)*(a.r+b.r)) - 1;
	}
	inline BOOL intersect(const C &c, const L &l){
		return less(dist2(l, c), c.r*c.r);
	}
	inline BOOL intersect(const C &c, const S &s){
		int d = less(dist2(s, c), c.r*c.r);
		if(d != TRUE) return d;
		int p = c.inside(s[0]), q = c.inside(s[1]);
		return (p<0 || q<0) ? BORDER : p&q;
	}
	
	/*
	 * CCWでs[0]->s[1]にかけてが共通部分
	 */
	inline S crosspoint(const C &c1, const C &c2){
		if(!intersect(c1, c2)) return S();
		R d = abs(c1 - c2);
		R x = (c1.r*c1.r - c2.r*c2.r + d*d) / (2*d);
		R h = sqrt(max(0., c1.r*c1.r - x*x));
		P u = unit(c2-c1);
		return S(c1 + u*x + u*P(0,-1)*h, c1 + u*x + u*P(0,1)*h);
	}
	inline P crosspoint(const L &l, const L &m){
		R A = outp(l.dir(), m.dir()), B = outp(l.dir(), l[1] - m[0]);
		if(!sig(abs(A)) && !sig(abs(B))) return m[0]; // same line
		if(abs(A) < EPS) assert(false); // !!!PRECONDITION NOT SATISFIED!!!
		return m[0] + B / A * (m[1] - m[0]);
	}
	inline S crosspoint(const C &c, const L &l){
		R d2 = dist2(l, c);
		if(c.r*c.r+EPS < d2) return S();
		P m = proj(c, l);
		P u = unit(l[1]-l[0]);
		R d = sqrt(max(.0, c.r*c.r - d2));
		return S(m+u*d, m-u*d);
	}
	inline vector<P> crosspoint(const C &c, const S &s){
		vector<P> res = crosspoint(c, (const L&)s);
		RREP(i, res.size()){
			if(inp(res[i]-s[0], s.dir())*inp(res[i]-s[1], -s.dir())<EPS)
				res.erase(res.begin() + i);
		}
		return res;
	}
	inline R commonarea(const C &a, const C &b){
		if(less(norm(a-b), (a.r-b.r)*(a.r-b.r)) == TRUE) return min(a.r*a.r, b.r*b.r)*PI;
		if(less((a.r+b.r)*(a.r+b.r), norm(a-b)) == TRUE) return .0;
		double d = abs(a-b);
		double rc = (d*d + a.r*a.r - b.r*b.r) / (2*d);
		double theta = acos(rc / a.r);
		double phi = acos((d - rc) / b.r);
		return a.r*a.r*theta + b.r*b.r*phi - d*a.r*sin(theta);
	}
	vector<L> CommonTangent(C c1, C c2){
		if(c1.r > c2.r) swap(c1, c2);
		double d = abs(c1-c2);
		vector<L> res;
		if(d < EPS) return res;
		if(d + EPS > c1.r + c2.r){
			// 内接線
			P crs = (c1*c2.r + c2*c1.r) / (c1.r + c2.r);
			double rad = asin(c1.r/abs(crs-c1));
			res.push_back(L(crs, crs + (c1-crs)*polar(1., rad)));
			res.push_back(L(crs, crs + (c1-crs)*polar(1., -rad)));
		}
		if(c1.r + d + EPS > c2.r){
			// 外接線
			double rad = 0.5*PI+asin((c2.r-c1.r) / d);
			P v = unit(c2-c1)*polar(1., rad);
			if(c1.r + d - EPS < c2.r){
				res.push_back(L(c1+v*c1.r, c1+v*c1.r+(c1-c2)*P(0, 1)));
			}else{
				res.push_back(L(c1+v*c1.r, c2+v*c2.r));
				v = 2.*proj(v, c2-c1) - v;
				res.push_back(L(c1+v*c1.r, c2+v*c2.r));
			}
		}
		return res;
	}
	
	struct min_ball {
		P center;
		R radius2;
		min_ball(const vector<P>& p) {
			FOR(it, p) ps.push_back(*it);
		}
		min_ball& compile() {
			m = 0;
			center = P(0, 0);
			radius2 = -1;
			make_ball(ps.end());
			return *this;
		}
	private:
		list<P> ps;
		list<P>::iterator supp_end;
		int m;
		P v[3], c[3];
		R z[3], r[3];
		void pop() { --m; }
		void push(const P& p) {
			if (m == 0) {
				c[0] = p; r[0] = 0;
			} else {
				R e = norm(p-c[m-1]) - r[m-1];
				P delta = p - c[0];
				v[m] = p - c[0];
				for (int i = 1; i < m; ++i)
					v[m] -= v[i] * inp(v[i], delta) / z[i];
				z[m] = inp(v[m], v[m]);
				c[m] = c[m-1] + e*v[m]/z[m]*.5;
				r[m] = r[m-1] + e*e/z[m]*.25;
			}
			center	= c[m];
			radius2 = r[m]; ++m;
		}
		void make_ball(list<P>::iterator i) {
			supp_end = ps.begin();
			if (m == 3) return;
			for (list<P>::iterator k = ps.begin(); k != i; ) {
				list<P>::iterator j = k++;
				if (norm(*j-center) > radius2) {
					push(*j); make_ball(j); pop();
					move_to_front(j);
				}
			}
		}
		void move_to_front(list<P>::iterator j) {
			if (supp_end == j) ++supp_end;
			ps.splice (ps.begin(), ps, j);
		}
	};
	
	struct Arrangement{
		struct AEdge{
			int u, v, t;
			R cost;
			AEdge(int u=0, int v=0, int t=0, R cost=0)
				:u(u), v(v), t(t), cost(cost){}
		};
		typedef vector<vector<AEdge>> AGraph;
		vector<P> p;
		AGraph g;
		Arrangement(){}
		Arrangement(vector<S> seg){
			int m = seg.size();
			REP(i, m){
				p.push_back(seg[i][0]);
				p.push_back(seg[i][1]);
				REP(j, i) if(sig(outp(seg[i].dir(), seg[j].dir())) && intersect(seg[i], seg[j]) == TRUE)
					p.push_back(crosspoint(seg[i], seg[j]));
			}
			sort(ALL(p)); UNIQUE(p);
			int n=p.size();
			g.resize(n);
			REP(i, m){
				S &s = seg[i];
				vector<pair<R, int>> ps;
				REP(j, n) if(s.online(p[j])) ps.emplace_back(norm(p[j] - s[0]), j);
				sort(ALL(ps));
				REP(j, (int)ps.size()-1){
					const int u=ps[j].second;
					const int v=ps[j+1].second;
					g[u].emplace_back(u, v, 0, abs(p[u] - p[v]));
					g[v].emplace_back(v, u, 0, abs(p[u] - p[v]));
				}
			}
		}
		
		int getIdx(P q){
			auto it = lower_bound(ALL(p), q);
			if(it == p.end() || *it != q) return -1;
			return it - p.begin();
		}
	};

	struct DualGraph{
		struct DEdge{
			int u, v, f, l;
			R a;
			DEdge(int u, int v, R a):u(u),v(v),f(0),l(0){
				while(PI < a) a -= 2*PI;
				while(a < -PI) a += 2*PI;
				this->a = a;
			}
			bool operator==(const DEdge &opp) const{
				return v==opp.v;
			}
			bool operator<(const DEdge &opp) const{
				return a>opp.a;
			}
			bool operator<(const R &opp) const{
				return a>opp;
			}
			friend ostream& operator<<(ostream &os, const DEdge &t) { return os<<"("<<t.u<<","<<t.v<<","<<t.a*180/PI<<")";}
		};
		
		int n;
		vector<P> p;
		vector<vector<DEdge>> g;
		UnionFind uf;
		DualGraph(const vector<P> &p):p(p),g(p.size()),n(p.size()),uf(p.size()){}
		void add_edge(const int s, const int t){
			R a = arg(p[t]-p[s]);
			g[s].emplace_back(s, t, a);
			g[t].emplace_back(t, s, a > 0 ? a-PI : a+PI);
			uf.unionSet(s, t);
		}
		vector<G> poly;
		
		void add_polygon(int s, int t, R a){
			auto e = lower_bound(ALL(g[s]), a-EPS);
			if(e == g[s].end()) e = g[s].begin();
			if(e->f) return;
			e->f = 1;
			e->l = t;
			poly[t].push_back(p[s]);
			add_polygon(e->v, t, e->a > 0 ? e->a-PI : e->a+PI);
		}
		
		void toSpanningTree(){
			vector<pair<R, pii>> e;
			REP(i, n)REP(j, i)if(!uf.findSet(i, j))
				e.emplace_back(norm(p[i]-p[j]), pii(i, j));
			sort(ALL(e));
			REP(ii, e.size()){
				const int i = e[ii].second.first;
				const int j = e[ii].second.second;
				if(uf.findSet(i, j)) continue;
				const S s(p[i], p[j]);
				if([&](){
					REP(k, n)if(i!=k&&j!=k){
						FOR(it, g[k])
						if(intersect(s, S(p[k], p[it->v])) == TRUE) return 0;
					}
					return 1;
				}()) add_edge(i, j);
			}
		}
		
		vector<vi> dual(){
			toSpanningTree();
			
			REP(i, n){
				sort(ALL(g[i]));
				UNIQUE(g[i]);
			}
			int s = min_element(ALL(p)) - p.begin();
			poly.emplace_back();
			add_polygon(s, poly.size()-1, -PI*.5);
			REP(i, n)REP(j, g[i].size())if(!g[i][j].f){
				poly.emplace_back();
				add_polygon(i, poly.size()-1, g[i][j].a+2.*EPS);
			}
			int m = poly.size();
			vector<vi> dg(m);
			vector<unordered_map<int, int>> rev(n);
			REP(i, n)REP(j, g[i].size()){
				int u = i, v = g[i][j].v, l = g[i][j].l;
				if(u>v) swap(u, v);
				if(rev[u].find(v) != rev[u].end()){
					if(l != rev[u][v]){
						dg[l].push_back(rev[u][v]);
						dg[rev[u][v]].push_back(l);
					}
				}
				else rev[u][v] = l;
			}
			REP(i, m){
				sort(ALL(dg[i]));
				UNIQUE(dg[i]);
			}
			return dg;
		}
	};

#undef SELF
#undef at
}

using namespace geom;

int f = 0;
namespace std{
	bool operator<(const P &a, const P &b){return sig(a.X-b.X) ? a.X < b.X : a.Y+EPS < b.Y;}
	bool operator==(const P &a, const P &b){return abs(a-b) < EPS;}
	istream& operator>>(istream &is, P &p){R x,y;is>>x>>y;p=P(x, y);return is;}
	istream& operator>>(istream &is, L &l){l.resize(2);return is >> l[0] >> l[1];}
	istream& operator>>(istream &is, C &c){return is >> (P &)c >> c.r;}
	const double B = 500;
	const double Z = 20;
	ostream& operator<<(ostream &os, const C &c){return os << "circle("<<B+Z*(c.X)<<", "<<1000-B-Z*(c.Y)<<", "<<Z*(c.r)<<")";}
	ostream& operator<<(ostream &os, const P &p){return os << C(p, 2./Z);}
	ostream& operator<<(ostream &os, const S &s){return os << "line("<<B+Z*(s[0].X)<<", "<<1000-B-Z*(s[0].Y)<<", "<<B+Z*(s[1].X)<<", "<<1000-B-Z*(s[1].Y)<<")";}
	ostream& operator<<(ostream &os, const G &g){REP(i, g.size()) cout << g.edge(i) << endl;return os;}

}

bool bipartite_matching_dfs(
	int v, const vector< vector<int> > &conn,
	vector<bool> &used, vector<int> &match)
{
	used[v] = true;
	for(int i = 0; i < conn[v].size(); ++i){
		int u = conn[v][i], w = match[u];
		if(w < 0 || (!used[w] && bipartite_matching_dfs(w, conn, used, match))){
			match[v] = u;
			match[u] = v;
			return true;
		}
	}
	return false;
}
//O(E√V)
int bipartite_matching(const vector< vector<int> > &conn){
	int res = 0;
	vector<int> match(conn.size(), -1);
	vector<bool> used(conn.size(), false);
	for(int v = 0; v < conn.size(); ++v){
		if(match[v] < 0){
			fill(used.begin(), used.end(), false);
			if(bipartite_matching_dfs(v, conn, used, match)){ ++res; }
		}
	}
	return res;
}

int n, k;

int main(int argc, char *argv[]){
	ios::sync_with_stdio(false);
	cin >> n >> k;
	vector<C> c(n);
	REP(i, n){
		cin >> c[i];
//		c[i] *= polar(1., 0);
	}
	vector<R> x;
	REP(i, n){
		x.push_back(c[i].X - c[i].r);
		x.push_back(c[i].X);
		x.push_back(c[i].X + c[i].r);
		REP(j, i){
			S s = crosspoint(c[i], c[j]);
			FOR(it, s){
				x.push_back(it->X);
			}
			if(s.size() == 2 && abs(s[0]-s[1])>EPS){
				x.push_back((c[i] + unit((s[0]+s[1])*0.5 - c[i]) * c[i].r).X);
				x.push_back((c[j] + unit((s[0]+s[1])*0.5 - c[j]) * c[j].r).X);
			}
		}
	}
	sort(ALL(x));UNIQUE(x);
//cerr << x << endl;
	vector<P> p;
	REP(i, n){
		REP(j, x.size()){
			L l(P(x[j], 0.), P(x[j], 10.));
			S s = crosspoint(c[i], l);
			FOR(it, s){
				p.push_back(*it);
			}
		}
	}
	EPS = 1e-3;
	sort(ALL(p));
//cerr << p << endl << endl;
	UNIQUE(p);
//FOR(it, p)cout << *it << endl;
	DualGraph dg(p);
	REP(i, n){
		vector<pair<R, int>> q;
		REP(j, p.size())
			if(!sig(abs(p[j] - c[i]) - c[i].r))
				q.emplace_back(arg(p[j] - c[i]), j);
		sort(ALL(q));
		REP(j, (int)q.size()) dg.add_edge(q[j].second, q[(j+1)%q.size()].second);
	}
	EPS = 1e-8;
	vector<vi> g = dg.dual();
//FOR(it, c) cout << *it << endl;
//FOR(it, dg.poly) cout << *it << endl;
//cout << dg.poly[atoi(argv[1])] << endl;
	if(k > 1) cout << dg.poly.size() - 1 << endl;
	else{
		REPS(i, (int)g.size()-1){
			g[i].erase(remove(ALL(g[i]), 0), g[i].end());
		}
		g[0].clear();
//		cerr << g << endl;
		cout << g.size() - bipartite_matching(g) - 1 << endl;
	}
	return 0;
}
accuracy: 0.2553191489361702
time_ms: 10
memory_kb: 1804
final_rank: 11