首页 > 其他分享 >CF1666K Kingdom Partition 题解

CF1666K Kingdom Partition 题解

时间:2022-12-24 18:45:00浏览次数:49  
标签:Kingdom cut int 题解 ll Partition tot inf

题意

给定 \(n\) 个点 \(m\) 条边的无向图,边有边权 \(l\)。

需要将点划分成 \(A,B,C\) 三个集合。

\(A\) 或 \(B\) 内部的边有 \(2l\) 的贡献,\(AC\) 或 \(BC\) 之间的边有 \(l\) 的贡献。

集合 \(A\) 必须包含点 \(a\),集合 \(B\) 必须包含点 \(b\),求最小贡献及其方案。

\(2\le n\le1000,0\le m\le2000\)

题解

这些限制看起来就比较最小割。

观察贡献有 \(2l\),那么一个点是得拆成两个的。

比较意识流地建一下图:对于 \(x,y,l\),连 \((x,y+n,l)\) 和 \((x+n,y,l)\) 两条无向边。

建图之后发现一条边两个端点类型对应的贡献是这样的:

\(ST\) \(TS\) \(SS\) \(TT\)
\(ST\) \(2\) \(0\) \(1\) \(1\)
\(TS\) \(0\) \(2\) \(1\) \(1\)
\(SS\) \(1\) \(1\) \(0\) \(2\)
\(TT\) \(1\) \(1\) \(2\) \(0\)

对比一下要求的矩阵:

\(A\) \(B\) \(C\)
\(A\) \(2\) \(0\) \(1\)
\(B\) \(0\) \(2\) \(1\)
\(C\) \(1\) \(1\) \(0\)

是前面的子矩阵。

需要保证 \(SS\) 和 \(TT\) 之间不会有贡献。其实直接跑最小割是就对的,因为假如某方案这两者之间有边,不如替换成同一种类型(显然是能够替换的)。

官方题解还有一种理解方式:\(\operatorname{cut}(x\cup y)+\operatorname{cut}(x\cap y)\le \operatorname{cut}(x)+\operatorname{cut}(y)\)。

于是 \(A\) 类点对应 \(ST\),\(B\) 类点对应 \(TS\),额外连边 \((s,a,\inf),(s,b+n,\inf),(a+n,t,\inf),(b,t,\inf)\) 即可。

代码:

#include <bits/stdc++.h>
using namespace std;
using ll=long long;
const int N=2005,M=2e4;
const ll inf=1e18;
int n,m,A,B,tot,s,t,op[N],d[N],b[N],v[M];
ll c[M];
vector<int> e[N];
void add(int x,int y,ll w){
	v[tot+1]=x;v[tot]=y;c[tot]=w;
	e[x].push_back(tot++);e[y].push_back(tot++);
}
bool bfs(){
	fill_n(d+1,t,0);fill_n(b+1,t,0);
	queue<int> q;
	q.push(s);d[s]=1;
	while(!q.empty()){
		int x=q.front();q.pop();
		for(int y:e[x]) if(!d[v[y]]&&c[y])
			d[v[y]]=d[x]+1,q.push(v[y]);
	}
	return d[t];
}
ll dfs(int x,ll w){
	if(x==t) return w;
	ll res=0;
	for(int i=b[x];i<e[x].size();i++){
		int y=e[x][i];
		if(d[v[y]]!=d[x]+1||!c[y]) continue;
		b[x]=i;
		ll k=dfs(v[y],min(w,c[y]));
		c[y]-=k;c[y^1]+=k;
		w-=k;res+=k;
		if(!w) return res;
	}
	return res;
}
void getop(int x){
	if(op[x]) return;
	op[x]=1;
	for(int y:e[x]) if(c[y]) getop(v[y]);
}
int main(){
	scanf("%d%d%d%d",&n,&m,&A,&B);
	t=(s=n*2+1)+1;
	add(s,A,inf);add(s,B+n,inf);
	add(A+n,t,inf);add(B,t,inf);
	for(int x,y,w;m--;)
		scanf("%d%d%d",&x,&y,&w),add(x,y+n,w),add(x+n,y,w),add(y+n,x,w),add(y,x+n,w);
	ll ans=0;
	while(bfs()) ans+=dfs(s,inf);
	getop(s);
	printf("%lld\n",ans);
	for(int i=1;i<=n;i++)
		if(op[i]==op[i+n]) putchar('C');
		else putchar(op[i]?'A':'B');
	return 0;
}

标签:Kingdom,cut,int,题解,ll,Partition,tot,inf
From: https://www.cnblogs.com/shrshrshr/p/17003194.html

相关文章

  • DTOJ 2022.12.24 测试 题解
    (2023省选模拟Round#1)测试成果50+0+0太菜了)A御神体这题写了四个多小时,最后还是没写出来ww莫队一直写挂(不过对莫队的理解加深了很多题目链接DTOJP4346题目大意......
  • 自动化测试神器playwright的安装及常见问题解决
    前言相信自动化测试的同学,对于另一个Python自动化测试神器selenium并不陌生,在playwright出现之前,selenium是自动化测试最常用的Python库,他支持多平台:windows、linux、MAC,且......
  • VsCode搭建C语言运行环境以及终端乱码问题解决
    在VsCode中搭建C/C++运行环境需要先安装以下插件1、安装c/c++插件2、安装coderunner插件当然也可以安装一些其他的美化插件根据个人习惯,但是以上这两个是必装的......
  • Codeforces 1097 G Vladislav and a Great Legend 题解 (DP)
    题目链接思路首先看到这种求\(x^k\)形式的,直接无脑转下降幂:\(x^k=\sum_{i=1}^kS2(k,i)\cdotx^{\underline{i}}\),其中\(S2\)表示第二类斯特林数,\(x^{\underlinei}\)表......
  • Codeforces 1097 G Vladislav and a Great Legend 题解 (DP)
    题目链接思路首先看到这种求\(x^k\)形式的,直接无脑转下降幂:\(x^k=\sum_{i=1}^kS2(k,i)\cdotx^{\underline{i}}\),其中\(S2\)表示第二类斯特林数,\(x^{\underlinei}\)表......
  • Codeforces 1097 G Vladislav and a Great Legend 题解 (DP)
    题目链接思路首先看到这种求\(x^k\)形式的,直接无脑转下降幂:\(x^k=\sum_{i=1}^kS2(k,i)\cdotx^{\underline{i}}\),其中\(S2\)表示第二类斯特林数,\(x^{\underlinei}\)表......
  • Codeforces 1097 G Vladislav and a Great Legend 题解 (DP)
    题目链接思路首先看到这种求\(x^k\)形式的,直接无脑转下降幂:\(x^k=\sum_{i=1}^kS2(k,i)\cdotx^{\underline{i}}\),其中\(S2\)表示第二类斯特林数,\(x^{\underlinei}\)表......
  • luoguP5383 普通多项式转下降幂多项式 题解
    学习了bztMinamoto大佬的做法,希望这篇题解可以使得那个方法更加易于理解。既然下降幂多项式转普通多项式可以采取分治\(\operatorname{NTT}\),那么可以猜测逆过来也可以......
  • CF1765J Hero to Zero 题解
    题意给出长为\(n\)数组\(a,b\),令\(c_{i,j}=|a_i-b_j|\)。每次可以花\(1\)的代价让矩阵\(c\)的一行或一列或一个格子减\(1\),也可以花\(-1\)的代价让一行或一列......
  • # Win10为知笔记Docker镜像部署 -v /wiz/storage问题解决
    Win10为知笔记Docker镜像部署-v/wiz/storage问题解决用了很长一段时间的为知笔记,客户端体验还行,服务端笔记同步体验不佳。准备用Docker自己搭一个服务端。环境:操作......