zoukankan      html  css  js  c++  java
  • 二分图题目

    矩阵游戏

    对于每一个黑块,我们将它横纵坐标连边。如果每个点都可以匹配上那么就有解。

    Sorting Slides

    将可以对应上的幻灯片和编号连上,我们枚举每一条边,将它删除。如果删除后最大匹配数不变,那么这条边不是匹配所必需的。否则说明每一种匹配都需要这条匹配边,即为答案之一。

    [JSOI2009]游戏

    考虑黑白染色,求出一组最大匹配。考虑先手选择非匹配点,后手一定只能再走到匹配点,否则的话与最大匹配矛盾。

    后手走到匹配点后先手沿着匹配边走,最后一定是后手无路可走。路径一定是 非匹配边 -> 匹配边 -> 非匹配边 -> ... -> 匹配边。假设最后是后手走的非匹配边,那么这必然是一条增广路,又与最大匹配不符。

    现在问题转化为一张二分图有多少个点可以删掉并且最大匹配数不变。我们可以分别从 (s,t) 轮流走非匹配边,匹配边,走到的同一侧的点就是可以删掉的非必要点。因为所走的路径也可以是一条增广路径(雾)。

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <queue>
    
    using namespace std;
    
    int read()
    {
    	int a = 0,x = 1;char ch = getchar();
    	while(ch > '9' || ch < '0') {if(ch == '-') x = -1;ch = getchar();}
    	while(ch >= '0' && ch <= '9') {a = a*10 + ch-'0';ch = getchar();}
    	return a*x;
    }
    const int N=1e6+7,inf=1e9+7;
    int n,m,s,t,x[] = {-1,0,0,1},y[] = {0,-1,1,0},bel[N],vis[N],ab[N],flag,dis[N],cur[N];
    char S[109];
    
    int head[N],go[N],nxt[N],cnt(1),lim[N],arr[107][107],id[107][107];
    void add(int u,int v,int w)
    {
    	go[++cnt] = v;
    	nxt[cnt] = head[u];
    	head[u] = cnt;
    	lim[cnt] = w;
    }
    
    bool BFS()
    {
    	for(int i = s;i <= t;i ++) dis[i] = 0;
    	queue<int>q;q.push(s);dis[s] = 1;
    	while(!q.empty()) {
    		int u = q.front();q.pop();
    		for(int e = head[u];e;e = nxt[e]) {
    			int v = go[e];if(dis[v] || !lim[e]) continue;
    			dis[v] = dis[u] + 1;q.push(v);
    		}
    	}
    	return dis[t];
    }
    
    int DFS(int u,int limit)
    {
    	if(u == t || !limit) return limit;
    	int ret = 0;
    	for(int &e = head[u];e;e = nxt[e]) {
    		int v = go[e];
    		if(dis[v] != dis[u] + 1 || !lim[e]) continue;
    		int tmp = DFS(v,min(limit,lim[e]));
    		limit -= tmp,ret += tmp;
    		lim[e] -= tmp,lim[e^1] += tmp;
    		if(!limit) break;
    	}
    	return ret;
    }
    
    void dfs(int u,int w)
    {
    	if(vis[u]) return ;
    	vis[u] = 1;
    	if(bel[u] == w) ab[u] = 1,flag = 1;
    	for(int e = head[u];e;e = nxt[e]) {
    		int v = go[e];if(lim[e] == w) dfs(v,w);
    	}
    }
    
    int main()
    {
    	// freopen("random.in","r",stdin);
    	// freopen("sol.out","w",stdout);
    	n = read(),m = read(),s = 0,t = n*m+1;
    	for(int i = 1;i <= n;i ++) {
    		scanf("%s",S+1);
    		for(int j = 1;j <= m;j ++) {
    			arr[i][j] = (S[j] == '.');
    			id[i][j] = (i-1)*n+j;
    		}
    	}
    	for(int i = 1;i <= n;i ++) {
    		for(int j = 1;j <= m;j ++) {
    			if(arr[i][j] && ((i+j)&1)) {
    				bel[id[i][j]] = 1;
    				add(s,id[i][j],1);add(id[i][j],s,0);
    				for(int k = 0;k < 4;k ++) {
    					int p = i+x[k],q = j+y[k];
    					if(arr[p][q] && p >= 1 && p <= m && q >= 1 && q <= m) add(id[i][j],id[p][q],1),add(id[p][q],id[i][j],0);
    				}
    			} else if(arr[i][j] && !((i+j)&1)) add(id[i][j],t,1),add(t,id[i][j],0);
    		}
    	}
    	int ans = 0;
    	for(int i = s;i <= t;i ++) cur[i] = head[i];
    	while(BFS()) {
    		ans += DFS(s,inf);
    		for(int i = s;i <= t;i ++) head[i] = cur[i];
    	}
    	dfs(s,1);memset(vis,0,sizeof(vis));dfs(t,0);
    	if(!flag) puts("LOSE");
    	else {
    		puts("WIN");
    		for(int i = 1;i <= n;i ++) {
    			for(int j = 1;j <= m;j ++) {
    				if(ab[id[i][j]]) printf("%d %d
    ",i,j);
    			}
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    Qt编译出错:“Cannot find file...... .pro."
    谈论如何有效地保护你的数据
    购书网
    VC非模态对话框创建和销毁
    在GUI程序中使用控制台的两种方法
    fatal error C1010: unexpected end of file while looking for precompiled header directive
    burp抓取手机包
    为firefox添加flash插件
    msfvenom生成linux后门
    kali下操作 Apache2
  • 原文地址:https://www.cnblogs.com/nao-nao/p/14676474.html
Copyright © 2011-2022 走看看