[BZOJ 1443]游戏Game

来源:互联网 发布:补血产品网络推广 编辑:程序博客网 时间:2024/06/06 05:52

二分图博弈



#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>#define maxn 110using namespace std;int n, m;bool mark[maxn][maxn];int M[maxn][maxn];#define N 500010struct Edge{int to, next;}edge[N];int h[N], cnt;void add(int u, int v){cnt ++;edge[cnt].to = v;edge[cnt].next = h[u];h[u] = cnt;}int vis[N], tim;const int dx[] = {0, 0, 1, -1};const int dy[] = {1, -1, 0, 0};int girl[N], lonely[N];bool find(int u){for(int i = h[u]; i; i = edge[i].next){int v = edge[i].to;if(vis[v] != tim){vis[v] = tim;if(girl[v] == 0 || find(girl[v])){girl[v] = u;girl[u] = v;return true;}}}return false;}bool istrue[N];void dfs(int u){if(u == 0)return;istrue[u] = true;for(int i = h[u]; i; i = edge[i].next){int v = edge[i].to;if(!istrue[girl[v]])    dfs(girl[v]);}}int main(){char ch;scanf("%d%d", &n, &m);int num = 0;for(int i = 1; i <= n; i ++){        for(ch = getchar(); ch < '!'; ch = getchar());        for(int j = 1; j <= m; j ++){mark[i][j] = ch == '.';num += mark[i][j];ch = getchar();    }}int Count = 0;for(int i = 1; i <= n; i ++)        for(int j = 1; j <= m; j ++)if(mark[i][j])    M[i][j] = ++ Count;    for(int i = 1; i <= n; i ++)        for(int j = 1; j <= m; j ++)            if(mark[i][j])for(int k = 0; k < 4; k ++){int u = i + dx[k], v = j + dy[k];if(u == 0 || u > n || v == 0 || v > m || mark[u][v] == 0)    continue;add(M[i][j], M[u][v]);add(M[u][v], M[i][j]);}int ans = 0;for(int i = 1; i <= Count; i ++){tim ++;if(!girl[i] && find(i))ans ++;}if(num == ans * 2){printf("LOSE");return 0;}printf("WIN\n");for(int i = 1; i <= Count; i ++){if(!girl[i]){tim ++;dfs(i);}}for(int i = 1; i <= n; i ++)for(int j = 1; j <= m; j ++)if(M[i][j] && istrue[M[i][j]])printf("%d %d\n", i, j);return 0;}



同。NOI2011兔兔与蛋蛋

#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>#define maxn 52using namespace std;int n, m, id[maxn][maxn], a[maxn][maxn];struct Edge{int to, next;}edge[1000010];int h[10010], cnt, ans[10010];void add(int u, int v){cnt ++;edge[cnt].to = v;edge[cnt].next = h[u];h[u] = cnt;}int read(){char ch = getchar();for(; ch < '!'; ch = getchar());if(ch == 'O')return 1;if(ch == 'X')return 2;if(ch == '.')return 3;}int girl[10010], vis[10010], tim, done[10010];int find(int x){if(done[x])return false;for(int i = h[x]; i; i = edge[i].next){int v = edge[i].to;if(vis[v] == tim || done[v])continue;vis[v] = tim;if(!girl[v] || find(girl[v])){girl[x] = v, girl[v] = x;return true;}}return false;}int s, t;int main(){scanf("%d%d", &n, &m);for(int i = 1; i <= n; i ++){for(int j = 1; j <= m; j ++){a[i][j] = read();if(a[i][j] == 3) s = i, t = j, a[i][j] = 2;}}int Cnt = 0;for(int i = 1; i <= n; i ++)for(int j = 1; j <= m; j ++)    if(a[i][j] == 1 ^ ((i + j) & 1) == ((s + t) & 1))id[i][j] = ++ Cnt;for(int i = 1; i <= n; i ++)    for(int j = 1; j <= m; j ++){if(!id[i][j])continue;if (id[i+1][j])    add(id[i][j], id[i+1][j]),    add(id[i+1][j], id[i][j]);if (id[i][j+1])    add(id[i][j], id[i][j+1]),add(id[i][j+1], id[i][j]);    }for(int i = 1; i <= Cnt; i ++)    if(!girl[i])tim ++, find(i);int test, pos;scanf("%d", &test);//ans代表第i个操作前,局面是否存在最大匹配//如果存在则局面为必败态for(int i = 1; i <= 2 * test ; i ++){done[pos = id[s][t]] = true;if(girl[pos]){int match = girl[pos];girl[pos] = girl[match] = 0;tim ++;ans[i] = !find(match);}scanf("%d%d", &s, &t);}int ret = 0;for(int i = 1; i <= test; i ++)    ret += ans[i * 2 - 1] & ans[i * 2];printf("%d\n", ret);for(int i = 1; i <= test; i ++)    if(ans[i * 2 - 1] & ans[i * 2])        printf("%d\n", i);return 0;}


0 0
原创粉丝点击