UVALive 5882 Racing Car Trail

来源:互联网 发布:淘宝买手机是正品吗 编辑:程序博客网 时间:2024/05/19 02:44

http://www.cnblogs.com/jffifa/archive/2011/12/17/2291069.html

二分图博弈:

1.博弈者人数为两人,双方轮流进行决策。
2.博弈状态(对应点)可分为两类(状态空间可分为两个集合),对应二分图两边(X集和Y集)。任意合法的决策(对应边)使状态从一类跳转到另一类。(正是由于这个性质使得问题可以用二分图描述)
3.不可以转移至已访问的状态。(不可重复访问点)
4.无法转移者判负。

现在问题变为从二分图指定起点开始轮流移动,不可重复访问点,无法移动判负。


如果起点是一个最大匹配的必需点,那么先手胜的方法是沿着匹配边走向下一个必需点。

如果起点是不是最大匹配点,或者是最大匹配点但不是必需点,那么这些点必定连向必需点(否则重新增广,最大匹配数加一),那么先手必败。

判定必需点的方法: 在图中删去这个点,保留其他匹配边,看这个点u所匹配的点v能否重新增广,如果能,则不是必需点。


代码:

#include<bits/stdc++.h>#define pb push_back#define fi first#define se secondusing namespace std;typedef long long ll;typedef pair<int, int> PII;const double PI = acos(-1.0);const double eps = 1e-10;int dcmp(double x) { if(fabs(x) < eps) return 0; else return x<0?-1:1; }const int INF = 0x3f3f3f3f;const int N = 1e2+5;char mp[N][N];int dir[4][2] = {{1,0}, {-1,0}, {0,1}, {0,-1}}, n, m, mark;int vis[N*N], lk[N*N];vector<int> G[N*N];void addedge(int x, int y) { G[x].pb(y); G[y].pb(x); }bool dfs(int u) {    for(int v:G[u]) if(vis[v] != mark) {        vis[v] = mark;        if(lk[v]==-1 || dfs(lk[v])) {            lk[v] = u;            return true;        }    }    return false;}int main() {    while(~scanf("%d%d", &n, &m)) {        if(!n && !m) break;        for(int i = 0; i < n; i++) {            scanf("%s", mp[i]);            for(int j = 0; j < m; j++) if(mp[i][j]!='X') {                G[i*m+j].clear(); vis[i*m+j] = 0; lk[i*m+j] = -1;                if(j>0 && mp[i][j-1]!='X') addedge(i*m+j, i*m+j-1);                if(i>0 && mp[i-1][j]!='X') addedge(i*m+j, (i-1)*m+j);            }        }        mark = 0;        for(int i = 0; i < n; i++) {            for(int j = 0; j < m; j++) if(mp[i][j]!='X' && (i+j)%2) {                mark++;                dfs(i*m+j);            }        }        for(int i = 0; i < n; i++) {            for(int j = 0; j < m; j++) if(mp[i][j]!='X' && !((i+j)%2)) {                int u = i*m+j;                if(lk[u] == -1) continue;                lk[lk[u]] = u;            }        }        for(int i = 0; i < n; i++) {            for(int j = 0; j < m; j++) {                if(mp[i][j] == 'X') { printf("X"); continue; }                int v= i*m+j;                if(lk[v] == -1) printf("B");                else {                    vis[v] = ++mark;                    int u = lk[v];                    if(dfs(u)) lk[v] = -1, printf("B");                    else printf("A");                }            }            printf("\n");        }        printf("\n");    }    return 0;}


原创粉丝点击