UVALive 6525 Attacking rooks 二分匹配 经典题
2014-10-30 00:15
387 查看
题目链接:点击打开链接题意:给定n*n的棋盘,可以在'.'上摆 象棋中的车(X是墙壁)使得任意两个车都不能互相攻击到问:最多能摆多少个车。思路:二分匹配1、若没有X,那么做法就是 X点集为行,Y点集为列,对于图上的每个点所在的行和列(x,y) 建一条边 x->y2、有了X,那么对于每个点所在的上方能接触到的X必须各不相同,所以给每个X标号,第一个X标记成n+13、这样X点集就是行(1-n) 和 n+1-siz (siz是X的个数)4、对于每个点,上方能接触到的最近的X作为列,右方能接触到的最近的Y作为行,建一条边 X->Y而处理每个点上方能接触到的最近的X就是一个dp,右方也是同样处理。然后跑个二分匹配就好。
<pre name="code" class="cpp">#pragma comment(linker, "/STACK:1024000000,1024000000")#include<bits/stdc++.h>template <class T>inline bool rd(T &ret) { char c; int sgn; if(c=getchar(),c==EOF) return 0; while(c!='-'&&(c<'0'||c>'9')) c=getchar(); sgn=(c=='-')?-1:1; ret=(c=='-')?0:(c-'0'); while(c=getchar(),c>='0'&&c<='9') ret=ret*10+(c-'0'); ret*=sgn; return 1;}template <class T>inline void pt(T x) { if (x <0) { putchar('-'); x = -x; } if(x>9) pt(x/10); putchar(x%10+'0');}using namespace std;const int N = 10105;struct Edge{ int to, nex;}edge[N*2];int head, edgenum;void init(){memset(head, -1, sizeof head); edgenum = 0;}void add(int u, int v){ Edge E = {v, head[u]}; edge[edgenum] = E; head[u] = edgenum++;}int lef, pn;int tim, T;bool match(int x){ for(int i=head[x]; ~i; i=edge[i].nex) { int v = edge[i].to; if(T[v] != tim) { T[v] = tim; if(lef[v] == -1 || match( lef[v] )) //match(lef[v]) : 原本连接v的X集点 lef[v] 能不能和别人连,如果能 则v这个点就空出来和x连 { lef[v] = x; return true; } } } return false;}int solve(){ int ans = 0; memset(lef, -1, sizeof(lef)); for(int i = 1; i<= pn; i++)//X集匹配,X集点标号从 1-pn 匹配边是G[左点].size() { tim++; if( match( i ) ) ans++; } return ans;}int n, siz, s[105][105], l[105][105], mp[105][105];char str[105];void input(){ siz = n; for(int i = 1; i <= n; i++) { scanf("%s", str+1); for(int j = 1; j <= n; j++){ if(str[j] == 'X') mp[i][j] = ++siz; else mp[i][j] = 0; } }}void build(){ for(int i = 1; i <= n; i++) s[0][i] = i; for(int i = 1; i <= n; i++) for(int j = 1; j <= n; j++) if(mp[i][j]) s[i][j] = mp[i][j]; else s[i][j] = s[i-1][j]; for(int i = 1; i <= n; i++) l[i][n+1] = i; for(int i = n; i; i--) { for(int j = 1; j <= n; j++) if(mp[j][i]) l[j][i] = mp[j][i]; else l[j][i] = l[j][i+1]; } init(); pn = siz; for(int i = 1; i <= n; i++) for(int j = 1; j <= n; j++) if(mp[i][j] == 0) add(l[i][j+1], s[i-1][j]);}int main(){ tim = 1; memset(T, 0, sizeof T); while(cin>>n){ input(); build(); cout<<solve()<<endl; } return 0;}/*5X....X......X...X.......X3.X.XXXXXX3.X.X.XXXX3.X.X.XX.X3.X.X.X.X.3XXXXXXXXX15XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX*/
相关文章推荐
- UVALive 6525 Attacking rooks 二分匹配 经典题
- 【二分匹配】 UVALive 6525 Attacking rooks
- 【二分匹配】 UVALive 6525 Attacking rooks
- UVaLive 6525 Attacking rooks (二分图最大匹配)
- UVALive - 6525 Attacking rooks
- UVALive 5903 Piece it together 二分匹配,拆点 难度:1
- UVALive 6525 Attacking rooks
- UVa live6492Welcome Party(二分最大匹配之最小点覆盖)
- uvalive 6525——Attacking rooks(二分图匹配,好题!)
- UVALive 6525 Attacking rooks
- LA 6525 Attacking rooks 二分匹配
- UVa live3415Guardian of Decency(二分最大匹配之最大独立点集)
- UVALive 6198 A Terribly Grimm Problem 二分匹配 求字典序最小解
- 2016China Final 二分 UVALive7900(D)
- Poj 2446 Chessboard 【二分匹配+经典建图模型】
- uvalive 4254(二分)
- UVALive - 3211 Now or later (【2-SAT】+【二分】)
- UVALive 3177 长城守卫(贪心+二分)
- UVALive 6275 (ACM-ICPC Live Archive: 6275 ) Joint Venture(二分)
- UVALIVE 2949 Elevator Stopping Plan(二分 + 贪心)