Toj 3345/hdu 1281 Chinese Chess 二分图匹配
2014-07-18 23:22
295 查看
题意:棋盘上有很多点,问最少设置几个棋子可以把这些点都吃掉,还问哪些棋子放置的位置是固定的,不然有些点就不能被吃掉
关键匹配:
先找到最大匹配。
然后对每个匹配边的两个端点u,v查看是否对应唯一的匹配边,
不优化会超时的。看了别人的代码才发现可以这样优化。太神奇了
其中有两处优化
关键匹配:
先找到最大匹配。
然后对每个匹配边的两个端点u,v查看是否对应唯一的匹配边,
不优化会超时的。看了别人的代码才发现可以这样优化。太神奇了
其中有两处优化
#include "stdio.h" #include "string.h" #include "queue" #include "vector" #include "algorithm" using namespace std; const int maxn = 10005; const int inf = 1<<30; int n,m,k,st,ed; vector<int>map[maxn],map1[maxn]; int cx[maxn],cy[maxn],Cx[maxn]; bool vis[maxn]; bool FindPath( int u ) { for( int i = 0; i < map[u].size(); i ++ ) { int v = map[u][i]; if( vis[v] ) continue; if( st == u && ed == v ) continue; vis[v] = 1; if( cy[v] == -1 || FindPath( cy[v] ) ) { cx[u] = v; cy[v] = u; return true; } } return false; } bool FindPathY( int v ) { for( int i = 0; i < map1[v].size(); i ++ ) { int u = map1[v][i]; if( vis[u] ) continue; if( st == u && ed == v ) continue; vis[u] = 1; if( cx[u] == -1 || FindPathY( cx[u] ) ) { cx[u] = v; cy[v] = u; return true; } } return false; } int MaxMatch() //二分图匹配 { int ans = 0; memset( cx,-1,sizeof(cx) ); memset( cy,-1,sizeof(cy) ); for( int i = 1; i <= n; i ++ ) //优化,枚举每条边,查看是否可以找到匹配边 { if( cx[i] == -1 ) { for( int j = 0; j < map[i].size() && cx[i] == -1; j ++ ) { int v = map[i][j]; if( cy[v] == -1 ) { cy[v] = i; cx[i] = v; ans ++; } } } } for( int i = 1; i <= n; i ++ ) //寻找增广路,增加匹配边 { if( cx[i] == -1 ) { memset( vis,0,sizeof(vis) ); ans += FindPath( i ); } } return ans; } int fun() { int ans = 0,flag; for( int i = 1; i <= n; i ++ ) Cx[i] = cx[i]; for( int i = 1; i <= n; i ++ ) { if( Cx[i] != -1 ) { flag = 0; //查看一条边的两个端点是否都没有增广路 等0即为关键点 st = i; ed = cx[i]; cx[st] = cy[ed] = -1; memset( vis,0,sizeof(vis) ); if( FindPath( st ) ) flag = 1; //判断左端点能否匹配其他点 else { memset( vis,0,sizeof(vis) ); if( FindPathY( ed ) ) flag = 1; //判断右端点能否匹配其他点 } if( !flag ) { cx[st] = ed; cy[ed] = st; ans ++; } else for( int j = i; j <= n; j ++ ) if( cx[j] != Cx[j] ) Cx[j] = -1; //如果在寻找增广路时,匹配边上的点发生变化,说明表示关键匹配, //下次无需再进行判断了 } } return ans; } int main() { #ifndef ONLINE_JUDGE freopen("data.txt","r",stdin); #endif int x,y,cas = 1; while( scanf("%d%d%d",&n,&m,&k)!=EOF ) { for( int i = 1; i <= n; i ++ ) map[i].clear(); for( int i = 1; i <= m; i ++ ) map1[i].clear(); for( int i = 0; i < k; i ++ ) { scanf("%d%d",&x,&y); map[x].push_back( y ); map1[y].push_back( x ); } st = ed = -1; int cur = MaxMatch(); int cnt = fun(); printf("Board %d have %d important blanks for %d chessmen.\n",cas ++,cnt,cur); } return 0; }
相关文章推荐
- HDU 1281 棋盘游戏(二分图匹配+匈牙利算法+模拟)
- 【二分图匹配】hdu 1281 棋盘游戏
- 【二分图匹配】棋盘游戏 HDU - 1281
- HDU 1281 棋盘游戏 二分图匹配
- 棋盘游戏 - HDU 1281 二分图匹配
- D - 棋盘游戏 - HDU 1281(二分图匹配)
- hdu1281 二分图匹配_必要边
- hdu 1281 棋盘游戏(二分图匹配--最小点覆盖)
- hdu 1281 二分图匹配
- hdu 1281 棋盘游戏 二分图匹配
- hdu 1281 棋盘游戏 二分图匹配;
- HDU 1281 棋盘游戏(二分图匹配)
- hdu 1281 棋盘游戏(二分图匹配)
- hdu1281(二分图匹配)
- 棋盘游戏 HDU - 1281(最大二分图匹配)
- C语言二分图匹配(4)___棋盘游戏(Hdu 1281)
- hdu 1281 棋盘游戏(二分图匹配)
- HDU 1281 棋盘游戏(二分图匹配)
- hdu 1281 (二分图匹配)
- HDU-1281 棋盘游戏 二分图匹配匈牙利算法