题意:你可进行两种操作,环操作和线操作,问你最小的操作次数下,所有点都消掉,明显的最小点覆盖,二分图匹配,这里用到了邻接矩阵存。kuangbin的Hopcroft -Carp模板
把极坐标的角度离散,然后用角度和极半径做二分图,然后进行最大匹配。
#include<iostream>
#include<cstdio>
#include<string.h>
#include<string>
#include<stack>
#include<set>
#include<algorithm>
#include<cmath>
#include<vector>
#include<map>
#include<sstream>
#include<queue>
#define ll long long
#define lll unsigned long long
#define eps 1e-8
#define mod 1000000007
#define clr(a) memset(a,0,sizeof(a))
#define clr1(a) memset(a,-1,sizeof(a))
#define lson l , m , rt << 1
#define rson m + 1 , r , rt << 1 | 1
using namespace std;
inline ll Max(ll a,ll b)
{
return a>b?a:b;
}
inline ll Min(ll a,ll b)
{
return a<b?a:b;
}
const int MAXN = 5000 + 500;
const int INF = 0x3f3f3f3f;
vector<int>G[MAXN];
int n;
int Mx[MAXN],My[MAXN];
int dx[MAXN],dy[MAXN];
int dis;
bool used[MAXN];
int w[MAXN];
bool SearchP()
{
queue<int>Q;
dis = INF;
memset(dx,-1,sizeof(dx));
memset(dy,-1,sizeof(dy));
for(int j = 0 ; j < n; j++)
{
int i = w[j];
if(Mx[i] == -1)
{
//cout<<i<<endl;
Q.push(i);
dx[i] = 0;
}
}
while(!Q.empty())
{
int u = Q.front();
Q.pop();
if(dx[u] > dis)break;
int sz = G[u].size();
for(int i = 0; i < sz; i++)
{
int v = G[u][i];
if(dy[v] == -1)
{
dy[v] = dx[u] + 1;
if(My[v] == -1)dis = dy[v];
else
{
dx[My[v]] = dy[v] + 1;
Q.push(My[v]);
}
}
}
}
return dis != INF;
}
bool DFS(int u)
{
int sz = G[u].size();
for(int i = 0; i < sz; i++)
{
int v = G[u][i];
if(!used[v] && dy[v] == dx[u] + 1)
{
used[v] = true;
if(My[v] != -1 && dy[v] == dis)continue;
if(My[v] == -1 || DFS(My[v]))
{
My[v] = u;
Mx[u] = v;
return true;
}
}
}
return false;
}
ll MaxMatch()
{
ll res = 0;
memset(Mx,-1,sizeof(Mx));
memset(My,-1,sizeof(My));
while(SearchP())
{
memset(used,false,sizeof(used));
for(int j = 0; j < n; j++)
{
int i = w[j];
if(Mx[i] == -1 && DFS(i))
res++;
}
}
return res;
}
int main()
{
#ifdef ONLINE_JUDGE
#else
freopen("an.txt","r", stdin);
#endif
int T;
ll ok;
int r,s,t;
scanf("%d",&T);
while(T--)
{
map<double,ll>flag;
ok = 1;
clr(w);
scanf("%d",&n);
for(int i = 1; i<5009; i++) G[i].clear();
for(int i = 0; i<n; i++)
{
scanf("%d%d%d",&r,&s,&t);
r = r - 1000;
w[i] = r;
if(!flag[t/s*1.0])
flag[t/s*1.0] = ok++;
//cout<<r<<" "<<flag[t/s*1.0]<<endl;
G[r].push_back(flag[t/s*1.0]);
}
ll ans = MaxMatch();
printf("%lld\n",ans);
}
return 0;
}