zoukankan      html  css  js  c++  java
  • [bzoj2150]部落战争_二分图最小路径覆盖

    部落战争 bzoj-2150

    题目大意题目链接

    注释:略。


    想法

    显然是最小路径覆盖,我们知道:二分图最小路径覆盖等于节点总数-最大匹配。

    所以我们用匈牙利或者dinic跑出最大匹配,然后用总结点数相减即可。

    最后,附上丑陋的代码... ...

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #define N 3000
    using namespace std;
    int n,m,r,c; int id;
    int line[N][N],fr[N],a[N][N],num[N][N];
    int dx[10],dy[10];
    bool used[N];
    bool find(int x)
    {
        for(int i=1;i<=id;i++) if(line[x][i]&&!used[i])
        {
            used[i]=true; if(!fr[i]||find(fr[i])) {fr[i]=x; return true;}
        }
        return false;
    }
    int main()
    {
    	scanf("%d%d%d%d",&n,&m,&r,&c);
    	char ch[60];
    	for(int i=1;i<=n;i++)
        {
    		scanf("%s",ch+1);
    		for(int j=1;j<=m;j++) if(ch[j]=='.')
            {
                num[i][j]=++id;
                a[i][j]=1;
            }
    	}
    	dx[1]=r;dx[2]=r;dx[3]=c;dx[4]=c;
    	dy[1]=c;dy[2]=-c;dy[3]=r;dy[4]=-r;
    	for(int i=1;i<=n;i++)
    		for(int j=1;j<=m;j++)
    			if(a[i][j])
    			for(int k=1;k<=4;k++)
                {
    				int x=i+dx[k],y=j+dy[k];
    				if(x<1||x>n||y<1||y>m) continue;
    				if (a[x][y]) line[num[i][j]][num[x][y]]=1;
    			}
    	int sum=0;
    	for(int i=1;i<=id;i++)
        {
    		memset(used,0,sizeof used);
    		if(find(i)) sum++;
    	}
    	printf("%d
    ",id-sum);
    	return 0;
    }
    

    小结:二分图的题还是要多刷题啊各位!

  • 相关阅读:
    [APIO2012]派遣
    Luogu_2774 方格取数问题
    Luogu4149 [IOI2011]Race
    Luogu_4886 快递员
    Loj_6282. 数列分块入门 6
    LOJ 6281 数列分块入门 5
    三维偏序 cdq
    【逆序对】 模板
    【luogu P1637 三元上升子序列】 题解
    【luogu P3609 [USACO17JAN]Hoof, Paper, Scissor蹄子剪刀布】 题解
  • 原文地址:https://www.cnblogs.com/ShuraK/p/9801792.html
Copyright © 2011-2022 走看看