ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

To_Heart—题解——[CQOI2017]老C的方块

2021-12-10 19:03:02  阅读:224  来源: 互联网

标签:Heart dist struct int 题解 1000005 zz CQOI2017 我们


这里提供一种更好想,但是点会多一些的做法

首先我们很容易就能想到染色

染色

我们按照以上方法染色,然后发现从 1 出发,沿着 1->2->3->4 的路线,可以把我们所有需要删除情况都涵盖完。

所以我们现在就只需要建图了

建图

因为我们可以沿着 1->2->3->4 的路线走完所有的情况,那么就可以建分层图了:

那么图与图之间怎么连边呢?我们就把一个点相邻的点,且染色颜色比它大 1 的点和它之间连一条边,边权为删去当前相邻点的代价。

但是我们直接连边会出现问题:

就像这张图一样,当我们删去了1和3之间的边,就相当于删去的节点3,但我们的2和3还是联通的,所以就会出现我们的点被删两次的情况。

所以我们要拆点,把点的点权转换为该点的两个点之间的边权,把两层之间的边权设为极大值就好了。

代码


#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int INF=0x3f3f3f3f;

struct zz{
	int u,w,id;
};
vector<zz> v[1000005];
struct Dinic{
	int dist[1000005],be[1000005];
	int s,t;
	void Add(int x,int y,int z){
//		printf("QwQ:%d %d %d\n",x,y,z);
		int idx=v[x].size(),idy=v[y].size();
		v[x].push_back((zz){y,z,idy});
		v[y].push_back((zz){x,0,idx});
	}
	bool BFS(){
		bool f=0;memset(dist,-1,sizeof dist);
		queue<int> q;q.push(s);
		dist[s]=be[s]=0;
		while(!q.empty()){
			int x=q.front();q.pop();
			int siz=v[x].size();
			for(int i=0;i<siz;i++){
				int y=v[x][i].u,w=v[x][i].w;
				if(!w||dist[y]!=-1) continue;
				q.push(y),be[y]=0,dist[y]=dist[x]+1;
				if(y==t) f=1;
			}
		}
		return f;
	}
	int DFS(int x,int sum){
		if(x==t||!sum) return sum;
		int siz=v[x].size(),ans=0;
		for(int i=0;i<siz;i++){
			int y=v[x][i].u,w=v[x][i].w,id=v[x][i].id;be[x]=i;
			if(!w||dist[x]!=dist[y]-1) continue;
			int now=DFS(y,min(sum-ans,w));
			if(!now) dist[y]=0;
			v[x][i].w-=now,v[y][id].w+=now,ans+=now;
		}
		return ans;
	}
	int dinic(){
		int ans=0,now=0;
		while(BFS()) while(now=DFS(s,INF)) ans+=now;
		return ans;
	}
}T;

int n,m,k,tot=0;

int qq[4]={3,4,1,2};
int qqq[4]={4,3,2,1};
int fx[5]={0,1,-1,0,0};
int fy[5]={0,0,0,1,-1};

bool Check(int x,int y){
	if(x<=0||x>n) return 0;
	if(y<=0||y>m) return 0;
	return 1;
}

struct ss{
	int x,y,col,val;
}a[1000005];

#define mp make_pair
#define pii pair<int,int> 
map<pii ,int > f;

signed main(){
	ios_base::sync_with_stdio(false);
	cin.tie(NULL), std::cout.tie(NULL);
	cin>>n>>m>>k;T.s=0,T.t=k*2+1;
	for(int i=1;i<=k;i++){
		cin>>a[i].x>>a[i].y>>a[i].val;
		swap(a[i].x,a[i].y);
		if(a[i].x&1) a[i].col=qqq[a[i].y%4];
		else a[i].col=qq[a[i].y%4];	
		f[mp(a[i].x,a[i].y)]=i;
	}
	for(int i=1;i<=k;i++){
		int x=a[i].x,y=a[i].y;
		T.Add(i,i+k,a[i].val);
		for(int kk=1;kk<=4;kk++){
			int qx=x+fx[kk],qy=y+fy[kk];
			if(!Check(qx,qy)||f.find(mp(qx,qy))==f.end()) continue;
			int id=f[mp(qx,qy)];
			if(a[id].col!=a[i].col+1) continue;
			T.Add(i+k,id,INF);
		}
		if(a[i].col==1) T.Add(T.s,i,INF);
		if(a[i].col==4) T.Add(i+k,T.t,INF);
	}
	cout<<T.dinic();
	return 0;
}


标签:Heart,dist,struct,int,题解,1000005,zz,CQOI2017,我们
来源: https://www.cnblogs.com/xf2056188203/p/15673454.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有