TopCoder SRM 589 Div1 450 GearsDiv1

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;
}

猜你喜欢

转载自blog.csdn.net/ymzqwq/article/details/82633231