棋盘游戏 HDU - 1281

原题链接

考察:二分图匹配+图论的基本操作

图论题目做多了看到这句不在这些格子上放车,也可以保证尽量多的“车”被放下,应该能反应过来是删边操作

其实我没反应过来

这道题和之前的HDU 1045一样也是缩点操作,通过这道题也搞明白了点之前的缩点操作,行集和列集有交集才能连边,然后就是走一波最大匹配,最后开始一条条删边,(这个边是缩点后的边,即在交集状态下的边,所以不能放在第一个for循环里)

但其实这道题根本不用缩点,给的行列就可以当作缩点后坐标

注意:

  1. match每次删边后初始化
 1 #include <iostream>
 2 #include <cstring>
 3 #include <algorithm>
 4 #include <map>
 5 using namespace std;
 6 typedef pair<int,int> pii;
 7 const int N = 110;
 8 pii p[N*N];
 9 int n,m,k,rmp[N][N],cmp[N][N],match[N*N],kcase,kcnt;
10 bool g[N][N],st[N*N];
11 map<int,int> rm,cm;
12 void inits()
13 {
14     rm.clear(); cm.clear(); kcnt = 0;
15     memset(rmp,0,sizeof rmp); memset(cmp,0,sizeof cmp);
16     memset(g,0,sizeof g); memset(match,-1,sizeof match); 
17 }
18 int Getrid(int x)
19 {
20     if(!rm.count(x)) rm[x] = rm.size();
21     return rm[x];
22 }
23 int Getcid(int x)
24 {
25     if(!cm.count(x)) cm[x] = cm.size();
26     return cm[x];
27 }
28 bool findw(int x)
29 {
30     for(int i=1;i<=cm.size();i++)
31     {
32         if(!g[x][i]||st[i]) continue;
33         st[i] = 1;
34         if(match[i]==-1||findw(match[i]))
35         {
36             match[i] = x;
37             return true;
38         }
39     }
40     return false;
41 }
42 int main()
43 {
44     while(scanf("%d%d%d",&n,&m,&k)!=EOF)
45     {
46         inits();
47         int res = 0,ans = 0;
48         for(int i=1;i<=k;i++)
49         {
50             int x,y; scanf("%d%d",&x,&y);
51             int row  = Getrid(x),col = Getcid(y);
52             rmp[x][y] = row,cmp[x][y] = col;
53         }
54         for(int i=1;i<=n;i++)
55           for(int j=1;j<=n;j++)
56             if(rmp[i][j]) { g[rmp[i][j]][cmp[i][j]] = 1; p[++kcnt].first = rmp[i][j],p[kcnt].second = cmp[i][j];} 
57         for(int i=1;i<=rm.size();i++)
58         {
59             memset(st,0,sizeof st);
60             if(findw(i)) res++;
61         } 
62         for(int j=1;j<=k;j++)
63         {
64             int x = p[j].first,y = p[j].second,tmp = 0;
65             g[x][y] = 0;
66             memset(match,-1,sizeof match); 
67             for(int i=1;i<=rm.size();i++)
68             {
69                 memset(st,0,sizeof st);
70                 if(findw(i)) tmp++;
71             }
72             if(tmp<res) ans++; 
73             g[x][y] = 1;
74         }
75         printf("Board %d have %d important blanks for %d chessmen.\n",++kcase,ans,res);
76     }
77     return 0;
78 }

 

posted @ 2021-01-23 17:35  acmloser  阅读(60)  评论(0编辑  收藏  举报