QAQ果然最多也就做个450pts的…至于500pts…呜呜
对于这题,我们可以发现,最优方案肯定是两种颜色的齿轮往同一个方向转,另一种颜色往另一个方向转。
比如说R和G都是顺时针旋转,那就要把R和G之间的边都删掉,我们发现R和G以及它们之间的边可以看做一个二分图,删去最少的点之后使所有点都不相连,剩下的一定是最大独立集。于是跑一遍最大匹配,匹配数就是要删的点数……
#include <bits/stdc++.h>
using namespace std;
const int N=51;
int n;
int g[N][N],c[N];
int b[N];
int mtx[N],mty[N];
int a[N][N];
template<class T> void checkmin(T &a,const T &b) { if (b<a) a=b; }
template<class T> void checkmax(T &a,const T &b) { if (b>a) a=b; }
class GearsDiv1 {
public:
int getmin( string color, vector<string> graph ) ;
};
int dfs(int x){
for(int i=1;i<=n;i++)
if (a[x][i]&&!b[i]){
b[i]=1;
if (!mty[i]||dfs(mty[i])){
mtx[x]=i;
mty[i]=x;
return 1;
}
}
return 0;
}
int GearsDiv1::getmin(string color, vector<string> gra) {
n=color.size();
for(int i=0;i<n;i++)
if (color[i]=='R') c[i+1]=0;
else if (color[i]=='G') c[i+1]=1;
else c[i+1]=2;
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
if (gra[i][j]=='Y') g[i+1][j+1]=1;
else g[i+1][j+1]=0;
int ans=n;
for(int i=0;i<3;i++)
for(int j=0;j<3;j++)
if (i!=j){
memset(a,0,sizeof a);
for(int k=1;k<=n;k++)
for(int l=1;l<=n;l++)
if (c[k]==i&&c[l]==j&&g[k][l]) a[k][l]=1;
int s=0;
memset(mtx,0,sizeof mtx);
memset(mty,0,sizeof mty);
for(int i=1;i<=n;i++)
if (!mtx[i]){
memset(b,0,sizeof b);
s+=dfs(i);
}
ans=min(ans,s);
}
return ans;
}