zoukankan      html  css  js  c++  java
  • 洛谷P4380 [USACO18OPEN]Multiplayer Moo

    题目

    第一问:

    用广搜类似用(floodfill)的方法。

    第二问:

    暴力枚举加剪枝,对于每个连通块,枚举跟这个连通块相连的其他与他颜色不同的连通块,然后向外扩展合并颜色与他们俩相同的连通块。扩展合并颜色的时候需要在以每个连通块为节点的图上广搜,每次都将不在当前双色连通块内连通块且颜色和当前双色其一相同的点加入队列。注意在建图的时候,只连接相邻的颜色不同的连通块,然后有每个边只会被扩展一次,因为边一定连接颜色不同的块,如果该边被遍历了,所以其实该边的双色连通块的两个颜色都确定了,也就找过了。而且防止出现多次计算的情况,我们枚举两个颜色连通块时,要满足编号小的不枚举,因为肯定在之间就已经枚举过了。

    #include <bits/stdc++.h>
    using namespace std;
    int n, maxn1, maxn2, abc, N, id, id2, cnt = 1, ma[256][256], lin[1001000];
    int vis1[256][256], vis2[1000010], fa[1010001], sum[1001011], color[1000011];//vis1记录的是每个点的连通块标号,sum记得是每个连通块的大小, color是每个连通块的颜色。 
    int di[5] = {0, 0, 1, -1};
    int dj[5] = {-1, 1, 0, 0};
    struct da {int i, j, num;} data[251 * 251]; int cmp(da a, da b){return a.num < b.num;}
    struct edg {int to, nex, vis;} e[1011100];
    inline void add(int f, int t)
    {
    	e[++cnt].to = t;
    	e[cnt].nex = lin[f];
    	lin[f] = cnt;
    }
    inline void init()
    {
    	scanf("%d", &n);
    	for (int i = 1; i <= n; i++)
    		for (int j = 1; j <= n; j++)
    			scanf("%d", &ma[i][j]);
    }
    void bfs(int i, int j)
    {
    	id++;
    	queue <int> qi, qj; 
    	qi.push(i);
    	qj.push(j);
    	color[id] = ma[i][j];
    	vis1[i][j] = id;
    	while (!qi.empty())
    	{
    		int ni = qi.front(); qi.pop();
    		int nj = qj.front(); qj.pop();
    		sum[id]++;
    		for (int i = 0; i < 4; i++)
    		{
    			int i1 = ni + di[i];
    			int j1 = nj + dj[i];
    			if (i1 > 0 && j1 > 0 && i1 <= n && j1 <= n && ma[i1][j1] == ma[ni][nj] && (!vis1[i1][j1]))
    				qi.push(i1), qj.push(j1), vis1[i1][j1] = id;
    			if (vis1[i1][j1] != id)
    				add(id, vis1[i1][j1]), add(vis1[i1][j1], id);//将他们的id相连 
    		}
    	}
    	maxn1 = max(maxn1, sum[id]);
    }
    void bfs2(int now, int end)
    {
    	queue <int> q;
    	vis2[now] = vis2[end] = ++id2;//一个连通块只能找一 
    	q.push(now), q.push(end);
    	int bfssum = 0;
    	while (!q.empty())
    	{
    		int cur = q.front();
    		q.pop();
    		bfssum += sum[cur];
    		for (int i = lin[cur]; i; i = e[i].nex)
    		{
    			int to = e[i].to;
    			if (vis2[to] == id2 || to < min(end, now) || (color[to] != color[now] && color[to] != color[end]) ) continue;
    			if (e[i].vis) continue;
    			e[i].vis = e[i ^ 1].vis = id2;
    			vis2[to] = id2;//  
    			q.push(to);
    		}
    	}
    	maxn2 = max(maxn2, bfssum);
    }
    int main()
    {
    	init();
    	for (int i = 1; i <= n; i++)
    		for (int j = 1; j <= n; j++)
    			if (!vis1[i][j]) 
    				bfs(i, j);
    	printf("%d
    ", maxn1);
    	for (int i = 1; i <= id; i++)//枚举每个连通块
    	{
    		for (int j = lin[i]; j; j = e[j].nex)
    		{
    			int to = e[j].to;
    			if (to <= i || e[j].vis) continue;
    			e[j].vis = e[j ^ 1].vis = 1;		
    			bfs2(i, to); 
    			if (maxn2 >= n * n / 2)
    				printf("%d", maxn2), exit(0);
    		}
    	}
    	printf("%d
    ", maxn2); 
    	return 0;
    }
    /*
    */ 
    

    https://www.luogu.org/problem/P4380

  • 相关阅读:
    Python神库分享之geoip2 IP定位库
    科普一下推荐引擎
    浏览器插件之王-Tampermonkey(油猴脚本)
    Swagger入门教程
    使用SonarQube+Eclipse来分析python代码
    什么是搜索引擎蜘蛛?
    让所有网站都提供API的Python库:Toapi
    如何提高自己的逻辑思维能力?
    推荐系统和搜索引擎的关系
    html 后台页面布局
  • 原文地址:https://www.cnblogs.com/liuwenyao/p/11769155.html
Copyright © 2011-2022 走看看