HDU1281 棋盘游戏(坐标平面 ,行列匹配+求关键点)
2015-08-15 18:01
519 查看
题意:略;
思路:把坐标X看做二分图的左边,Y看做右边,结合二分图的最大匹配,左右顶点形成的最大匹配边,就是不同行不同列。求关键点,就依次枚举删掉某一个边后是否会使匹配变小
思路:把坐标X看做二分图的左边,Y看做右边,结合二分图的最大匹配,左右顶点形成的最大匹配边,就是不同行不同列。求关键点,就依次枚举删掉某一个边后是否会使匹配变小
#include<iostream> #include<cstdlib> #include<cmath> #include<algorithm> #include<cstring> #include<cstdio> #include<queue> #include<set> #include<stack> #define cl(a,b) memset(a,b,sizeof(a)); #define LL long long #define P pair<int,int> #define X first #define Y second #define pb push_back using namespace std; const int maxn=150; const int inf=9999999; const int mod=100007; int G[maxn][maxn]; int x[maxn*maxn],y[maxn*maxn]; int matching[maxn]; bool vis[maxn]; int n,m,k; bool dfs(int u){ for(int i=0;i<m;i++)if(G[u][i]){ int v=i; if(vis[v])continue; vis[v]=true; if(matching[v]==-1||dfs(matching[v])){ matching[v]=u; return true; } } return false; } int hungar(){ int ans=0; cl(matching,-1); for(int i=0;i<n;i++){ cl(vis,false); if(dfs(i))ans++; } return ans; } int main(){ int cas=1; while(~scanf("%d%d%d",&n,&m,&k)){ cl(G,0); for(int i=0;i<k;i++){ scanf("%d%d",&x[i],&y[i]); x[i]--;y[i]--; G[x[i]][y[i]]=1; } int ans=0; int mx=hungar(); // printf("===%d\n",mx); for(int i=0;i<k;i++){ G[x[i]][y[i]]=0;//删除 if(hungar()<mx)ans++; G[x[i]][y[i]]=1;//复原 } printf("Board %d have %d important blanks for %d chessmen.\n",cas++,ans,mx); } return 0; }