zoukankan      html  css  js  c++  java
  • hdu 1507【Uncle Tom's Inherited Land*】

    #include <cstdio>
    #include <cstring>
    #include <vector>
    using namespace std;
    
    vector<int> land[100];
    int link[100];
    bool vis[100];
    int g[110][110];
    bool vis2[100];
    int pond[100];
    int n,m,k;
    
    bool can(int x)
    {
    	int len = land[x].size();
    	for(int i = 0;i < len;i ++)
    	{
    		int t = land[x].at(i);
    		if(!vis[t])
    		{
    			vis[t] = true;
    			if(link[t] == -1 || can(link[t]))
    			{
    				link[t] = x;
    				return true;
    			}
    		}
    	}
    
    	return false;
    }
    
    int maxmatch(int count)
    {
    	int num = 0;
    	memset(link,-1,sizeof(link));
    	for(int i = 1;i <= count;i ++)
    	{
    		memset(vis,false,sizeof(vis));
    		if(can(i))
    			num ++;
    	}
    	/*for(int i = 1;i <= count;i ++)
    	{
    		if(link[i] != -1)
    			printf("link[%d]:%d\n",i,link[i]);
    	}*/
    
    	return num;
    }
    
    void print()
    {
    	memset(vis2,false,sizeof(vis2));
    	for(int i = 1;i <= n;i ++)
    	{
    		for(int j = 1;j <= m;j ++)
    		{
    			if(g[i][j]&&!vis2[g[i][j]]&&link[g[i][j]] != -1&&!vis2[link[g[i][j]]])
    			{
    				int ax = (g[i][j] + pond[g[i][j]] - 1)/m + 1;//pond的作用就在这里,将编号还原为矩形的一格一格编号
    				int ay = (g[i][j] + pond[g[i][j]]-1)%m+1;
    				int bx = (link[g[i][j]] + pond[link[g[i][j]]] - 1)/m +1;
    				int by = (link[g[i][j]] + pond[link[g[i][j]]]-1) % m+1;
    				vis2[g[i][j]] = true;//将访问过的点标记
    				vis2[link[g[i][j]]] = true;
    				printf("(%d,%d)--(%d,%d)\n",ax,ay,bx,by);
    			}
    		}
    	}
    
    	printf("\n");
    }
    
    int main()
    {
    	while(scanf("%d%d",&n,&m),n || m)
    	{
    		memset(g,-1,sizeof(g));
    		memset(pond,0,sizeof(pond));
    		scanf("%d",&k);
    		for(int i = 0;i < 55;i ++)
    		{
    			land[i].clear();
    		}
    		for(int i = 0;i < k;i ++)
    		{
    			int a,b;
    			scanf("%d%d",&a,&b);
    			g[a][b] = 0;
    		}
    
    		int t = 0;
    		int count = 1;
    		for(int i = 1;i <= n;i ++)
    		{
    			for(int j = 1;j <= m;j ++)
    			{
    				if(g[i][j] == 0)
    				{
    					t ++;
    				}
    				else
    				{
    					pond[count] = t;//记录land前面pond的个数
    					//printf("pond[%d]:%d\n",count,t);
    					g[i][j] = count ++;//给每个land编号
    				}
    			}
    		}
    
    		for(int i = 1;i <= n;i ++)
    		{
    			for(int j = 1;j <= m;j ++)
    			{
    				//printf("%d ",g[i][j]);
    				if(g[i][j] != 0)
    				{
    					if(i-1>0&&g[i-1][j] != 0)
    					{
    						land[g[i][j]].push_back(g[i-1][j]);
    					}
    					if(i +1 <=m && g[i+1][j] != 0)
    					{
    						land[g[i][j]].push_back(g[i + 1][j]);
    					}
    					if(j - 1> 0&& g[i][j -1] != 0)
    					{
    						land[g[i][j]].push_back(g[i][j-1]);
    					}
    					if(j + 1 <= n&&g[i][j + 1] != 0)
    					{
    						land[g[i][j]].push_back(g[i][j+1]);
    					}
    				}
    			}
    			//printf("\n");
    		}
    
    		printf("%d\n",maxmatch(count - 1) / 2);
    		print();
    	}
    
    	return 0;
    }
    

    一A,太兴奋了,(*^__^*) 嘻嘻……而且效率还蛮不错滴 15MS 292K。

    二分匹配来着,只不过题目要求我们输出匹配的方案

    本来之前打算来个暴力的,但是N*M可达1万,然后嘞,题目又说N*M-K<=50,就改变策略了,给不是池塘的land编号,并记录每个land前面的池塘数目(记录池塘的数目是方便输出的,题目要求我们输出匹配的行与列,反正land也就50个),这样编号的land最多也就50个了。

    可是就是还有人0ms过的,(~ o ~)~zZ崇拜

  • 相关阅读:
    [HNOI2002]营业额统计
    HDU 1374
    HDU 3345
    HDU 2089
    Graham扫描法
    Codeforces 1144D Deduction Queries 并查集
    Codeforces 916E Jamie and Tree 线段树
    Codeforces 1167F Scalar Queries 树状数组
    Codeforces 1167E Range Deleting
    Codeforces 749E Inversions After Shuffle 树状数组 + 数学期望
  • 原文地址:https://www.cnblogs.com/Shirlies/p/2497987.html
Copyright © 2011-2022 走看看