#BFS,二进制#CF1776J Italian Data Centers

洛谷题面
CF1776J


分析

将原图的点所拆开的点按二进制编号,那么同一个点之间连边当且仅当恰好一个二进制位不同,

不同点之间连边颜色相同则其二进制相同,否则完全相反。

可以钦定起点就是 \((x,0)\) 那么需要记录经过了多少次因颜色不同而二进制取反的边,

因为同一个点到达其它二进制完全可以放到最后完成,那么设 \(dis[y][0/1]\) 表示从点 \(x\) 出发到达点 \(y\) 经过偶/奇条边的最短距离

那么最后枚举终点二进制位 \(1\) 的个数,可以取反奇数次将 \(1\) 删除,或者取反偶数次将 \(1\) 补齐,这样时间复杂度为 \(O(nm+n^2k)\)


代码

#include <cstdio>
#include <cctype>
#include <queue>
using namespace std;
const int N=111; struct node{int y,next;}e[N*N];
int dis[N][2],ans,n,m,k,a[N],as[N],et=1; queue<int>q;
int iut(){
	int ans=0; char c=getchar();
	while (!isdigit(c)) c=getchar();
	while (isdigit(c)) ans=ans*10+c-48,c=getchar();
	return ans;
}
void bfs(int st){
	for (int i=1;i<=n;++i) dis[i][0]=dis[i][1]=0x3f3f3f3f;
	dis[st][0]=0,q.push(st<<1);
	while (!q.empty()){
		int x=q.front()>>1,z=q.front()&1; q.pop();
		for (int i=as[x];i;i=e[i].next){
			int Z=z^(a[x]!=a[e[i].y]);
			if (dis[e[i].y][Z]>dis[x][z]+1){
				dis[e[i].y][Z]=dis[x][z]+1;
				q.push(e[i].y<<1|Z);
			}
		}
	}
}
int main(){
	n=iut(),m=iut(),k=iut();
	for (int i=1;i<=n;++i) a[i]=iut();
	for (int i=1;i<=m;++i){
		int x=iut(),y=iut();
		e[++et]=(node){y,as[x]},as[x]=et;
		e[++et]=(node){x,as[y]},as[y]=et;
	}
	for (int i=1;i<=n;++i){
		bfs(i);
		for (int x=1;x<=n;++x)
		for (int j=0;j<=k;++j)
		    ans=max(ans,min(dis[x][0]+j,dis[x][1]+k-j));
	}
	return !printf("%d",ans);
}
posted @ 2023-10-25 08:44  lemondinosaur  阅读(8)  评论(0编辑  收藏  举报