HDU1281-棋盘游戏-二分图匹配

先跑一个二分图匹配,然后一一删去匹配上的边,看能不能达到最大匹配数,不能这条边就是重要边

  1 /*--------------------------------------------------------------------------------------*/
  2
  3 #include <algorithm>
  4 #include <iostream>
  5 #include <cstring>
  6 #include <ctype.h>
  7 #include <cstdlib>
  8 #include <cstdio>
  9 #include <vector>
 10 #include <string>
 11 #include <queue>
 12 #include <stack>
 13 #include <cmath>
 14 #include <set>
 15 #include <map>
 16
 17 //debug function for a N*M array
 18 #define debug_map(N,M,G) printf("\n");for(int i=0;i<(N);i++) 19 {for(int j=0;j<(M);j++){ 20 printf("%d",G[i][j]);}printf("\n");}
 21 //debug function for int,float,double,etc.
 22 #define debug_var(X) cout<<#X"="<<X<<endl;
 23 #define LL long long
 24 const int INF = 0x3f3f3f3f;
 25 const LL LLINF = 0x3f3f3f3f3f3f3f3f;
 26 /*--------------------------------------------------------------------------------------*/
 27 using namespace std;
 28
 29 int N,M,E,T;
 30 const int maxn = 1000;
 31 vector <int> G[maxn];
 32 int uN;
 33 int Mx[maxn],My[maxn];
 34 int dx[maxn],dy[maxn];
 35 int dis;
 36 bool used[maxn];
 37 bool searchP()
 38 {
 39     queue<int> Q;
 40     dis = INF;
 41     memset(dx,-1,sizeof dx);
 42     memset(dy,-1,sizeof dy);
 43     for(int i=1;i<=uN;i++)
 44     {
 45         if(Mx[i] == -1)
 46         {
 47             Q.push(i);
 48             dx[i] = 0;
 49         }
 50     }
 51     while(!Q.empty())
 52     {
 53         int u = Q.front();
 54         Q.pop();
 55         if(dx[u] > dis) break;
 56         int sz = G[u].size();
 57         for(int i=0;i<sz;i++)
 58         {
 59             int v = G[u][i];
 60             if(dy[v] == -1)
 61             {
 62                 dy[v] = dx[u] + 1;
 63                 if(My[v] == -1) dis = dy[v];
 64                 else
 65                 {
 66                     dx[My[v]] = dy[v] + 1;
 67                     Q.push(My[v]);
 68                 }
 69             }
 70         }
 71     }
 72     return dis != INF;
 73 }
 74 bool DFS(int u)
 75 {
 76     int sz = G[u].size();
 77     for(int i=0;i<sz;i++)
 78     {
 79         int v = G[u][i];
 80         if(!used[v] && dy[v] == dx[u]+1)
 81         {
 82             used[v] = true;
 83             if(My[v] != -1 && dy[v] == dis) continue;
 84             if(My[v] == -1 || DFS(My[v]))
 85             {
 86                 My[v] = u;
 87                 Mx[u] = v;
 88                 return true;
 89             }
 90         }
 91     }
 92     return false;
 93 }
 94 int MaxMatch()
 95 {
 96     int res = 0;
 97     memset(Mx,-1,sizeof Mx);
 98     memset(My,-1,sizeof My);
 99     while(searchP())
100     {
101         memset(used,false,sizeof used);
102         for(int i=1;i<=uN;i++)
103         {
104             if(Mx[i] == -1 && DFS(i)) res++;
105         }
106     }
107     return res/2;
108 }
109
110 vector <pair<int,int> > save;
111 set <pair<int,int> > st;
112 int cas;
113 int main()
114 {
115     while(~scanf("%d%d%d",&N,&M,&E))
116     {
117         uN = N+M;
118         for(int i=0;i<maxn;i++) G[i].clear();
119         save.clear();
120         for(int i=0,a,b;i<E;i++)
121         {
122             scanf("%d%d",&a,&b);
123             G[a].push_back(N+b);
124             G[N+b].push_back(a);
125             save.push_back(make_pair(a,N+b));
126         }
127
128         st.clear();
129         int match = MaxMatch();
130         //printf("MaxMatch:%d\n",match);
131         for(int i=1;i<=N;i++)
132         {
133             if(Mx[i] != -1) st.insert(make_pair(i,Mx[i]));
134         }
135         int imp = 0;
136         for(auto it = st.begin();it != st.end();it++)
137         {
138             pair<int,int> cur = *it;
139             //printf("delete [%d,%d]\n",cur.first,cur.second);
140             for(int i=0;i<maxn;i++) G[i].clear();
141             for(int i=0;i<save.size();i++) if(save[i] != cur)
142             {
143                 int a = save[i].first,b = save[i].second;
144                 G[a].push_back(b);
145                 G[b].push_back(a);
146             }
147             if(MaxMatch() < match) imp++;
148         }
149         printf("Board %d have %d important blanks for %d chessmen.\n",++cas,imp,match);
150     }
151 }
时间: 2024-10-09 05:44:04

HDU1281-棋盘游戏-二分图匹配的相关文章

hdu-1281.棋盘游戏(二分图匹配 + 二分图关键点查询)

棋盘游戏 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 7898    Accepted Submission(s): 4600 Problem Description 小希和Gardon在玩一个游戏:对一个N*M的棋盘,在格子里放尽量多的一些国际象棋里面的“车”,并且使得他们不能互相攻击,这当然很简单,但是Gardon限制了只有某些格

hdu1281棋盘游戏(二分匹配,最小顶点覆盖)

Problem Description 小希和Gardon在玩一个游戏:对一个N*M的棋盘,在格子里放尽量多的一些国际象棋里面的"车",并且使得他们不能互相攻击,这当然很简单,但是Gardon限制了只有某些格子才可以放,小希还是很轻松的解决了这个问题(见下图)注意不能放车的地方不影响车的互相攻击. 所以现在Gardon想让小希来解决一个更难的问题,在保证尽量多的"车"的前提下,棋盘里有些格子是可以避开的,也就是说,不在这些格子上放车,也可以保证尽量多的"车

hdu 1281 棋盘游戏(二分图匹配)

棋盘游戏 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 2786    Accepted Submission(s): 1630 Problem Description 小希和Gardon在玩一个游戏:对一个N*M的棋盘,在格子里放尽量多的一些国际象棋里面的"车",并且使得他们不能互相攻击,这当然很简单,但是Gardon限制

HDU 1281 棋盘游戏(二分图匹配)

解题思路: 枚举棋盘上所有格子,如果讲该点删除后,最大匹配数会减少,则该点为关键点. #include <iostream> #include <cstring> #include <cstdlib> #include <cstdio> #include <vector> #include <algorithm> using namespace std; const int MAXN = 100 + 10; int G[MAXN][M

棋盘游戏(二分图匹配)

题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=1281 棋盘游戏 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 3200    Accepted Submission(s): 1897 Problem Description 小 希和Gardon在玩一个游戏:对一个N*M的棋盘,在格子里放

hdu------1281 棋盘游戏(最小覆盖点)

棋盘游戏 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 2492    Accepted Submission(s): 1452 Problem Description 小 希和Gardon在玩一个游戏:对一个N*M的棋盘,在格子里放尽量多的一些国际象棋里面的“车”,并且使得他们不能互相攻击,这当然很简单,但是 Gardon限制了只有某

HDU 1281 棋盘游戏 行列匹配

题目来源:HDU 1281 棋盘游戏 题意:有一些点可以放车 放的时候不能相互攻击到 求出哪一些点必须放 不放就不能得到最大的匹配 思路:行列匹配 矩阵的每一个点对于二分图的每一条边 首先求出最大匹配ans 然后如果每次去掉一个点然后再重新求最大匹配 很耗时 可以把第一次二分匹配的图存着 然后那些关键点肯定是是匹配的边 枚举去掉那一个格点(就是去掉一条已经匹配边)如果还能匹配 那么该格点就不是关键点 关键就是不要每次重新再求最大匹配 #include <cstdio> #include <

POJ2584 T-Shirt Gumbo 二分图匹配(网络流)

1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 5 const int inf=0x3f3f3f3f; 6 const int sink=30; 7 8 struct Edge 9 { 10 int to; 11 int next; 12 int capacity; 13 14 void assign(int t,int n,int c) 15 { 16 to=t; next=n; ca

BZOJ 1854 游戏(二分图匹配或并查集)

此题的二分图匹配做法很容易想,就是把属性当做s集,武器当做t集,如果该武器拥有该武器则连一条边. 那么答案就是求该二分图的最大前i个匹配.将匈牙利算法改一改,当前找不到增广路就break. 但是过这个题需要常数优化,不能每次都fillchar一遍used数组.可以用队列将使用的used点加入,然后需要初始化的时候弹出即可. # include <cstdio> # include <cstring> # include <cstdlib> # include <i

HDU 3081:Marriage Match II(二分图匹配+并查集)

http://acm.hdu.edu.cn/showproblem.php?pid=3081 题意:有n个男生n个女生,他们只有没有争吵或者女生a与男生A没有争吵,且女生b与女生a是朋友,因此女生b也可以和男生A过家家(具有传递性).给出m个关系,代表女生a和男生b没有争吵过.给出k个关系,代表女生a与女生b是好朋友.每一轮过家家之后,女生只能选择可以选择并且没选过的男生过家家,问游戏能进行几轮. 思路:因为n<=100,因此支持O(n^3)的算法,挺容易想到是一个二分图匹配的.(出现在我的网络