2021江苏省赛-Anti-merge-(思维转化+二分图)

72 篇文章 1 订阅
54 篇文章 2 订阅

J

题意:
刚开始这个题意就很难懂,就是给你n*m的格子,每个格子有个编号,如果两个相同的编号相邻那么他们就会合并,除非你对其中一个进行颜色标记。现在问你最少用多少种颜色可以不让原本的格子合并,在用这些颜色的前提下最少要颜色多少次。

思考:
刚开始我感觉就是先找出来最少的颜色数,然后再用这些颜色去二分最少次数,但是没法check,然后就僵住了。过了会周来了句应该就是用1种颜色染就行了,然后恍然大悟,之后我以为就是没有上司的舞会,最少的颜色次数嘛,但是这个图是可能有环的然后就不行了,之后于说就对这个图染色,奥奥到这才明白就是二分图直接颜色,一个连通块其中一个点的颜色确定好之后剩下的都确定了,染就完了,然后染完取颜色最少的那个去标记就行了。记得人家要的输出格式,既然这样的输出就一定有他的道理,就算树上dp跑也只能是求出来最小次数,具体方案没法求。

代码:

#include<bits/stdc++.h>
#define int long long
#define pb push_back
#define PII pair<int,int >  
#define fi first
#define se second
#define IOS std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);

using namespace std;

const int N = 3e5+5,M = 505;

int T,n,m;
int va[M][M];
int col[N];
int cnt[5];
PII mp[N];
int dx[4] = {1,-1,0,0};
int dy[4] = {0,0,1,-1};

vector<int > e[N];
vector<PII > v;
vector<int > anw;


int get(int x,int y)
{
	return m*(x-1)+y;
}

void dfs(int now,int p)
{
	col[now] = 3-col[p];
	cnt[col[now]] += 1;
	v.pb({now,col[now]});
	for(auto spot:e[now])
	{
		if(spot==p) continue;
		if(!col[spot]) dfs(spot,now);
	}
}

signed main()
{
	IOS;
	cin>>n>>m;
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=m;j++)
		{
			cin>>va[i][j];
			mp[get(i,j)] = {i,j};
		}
	}
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=m;j++)
		{
			for(int k=0;k<4;k++)
			{
				int x = i+dx[k],y = j+dy[k];
				if(x<1||x>n||y<1||y>m||va[x][y]!=va[i][j]) continue;
				int a = get(i,j),b = get(x,y);
				e[a].pb(b);e[b].pb(a);
			}
		}
	}
	col[0] = 1;
	for(int i=get(1,1);i<=get(n,m);i++)
	{
		if(!col[i])
		{
			cnt[1] = cnt[2] = 0;
			v.clear();
			dfs(i,0);
			if(cnt[1]<cnt[2])
			{
				for(auto t:v)
				if(t.se==1) anw.pb(t.fi);
			}
			else
			{
				for(auto t:v)
				if(t.se==2) anw.pb(t.fi);
			}
		}
	}
	if(anw.size()==0) cout<<0<<" ";
	else cout<<1<<" ";
	cout<<anw.size()<<"\n";
	for(auto t:anw)
	{
		cout<<mp[t].fi<<" "<<mp[t].se<<" "<<1<<"\n";
	}
	return 0;
}

总结:
多多思考,注意细节和特判,特别是输出的时候。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值