ARC089E题解

想不到的高明构造。记录一下好了。

对于不同的 \((x,y)\),很显然最麻烦的事情是我们并不知道路径上有多少个 \(x,y\)

那就构造一个好了。设 \(f[i][j]\) 表示 \((s,t)\) 路径上一共有 \(i\)\(x\)\(j\)\(y\),路径上除去 \(x,y\) 的边权之和。

那么显然有 \(d[x][y]=\min(f[i][j]+i\times x+j\times y)\),变成不等式就是 \(d[x][y]\leq f[i][j]+i\times x+j\times y\)

最后能够得到 \(d[x][y]-i\times x-j\times y\leq f[i][j]\),也就是说 \(f[i][j]=\max(d[x][y]-i\times x-j\times y\)

那么如何构造一张图使得上述条件满足?

显然 \(x,y\) 最多只能有 \(100\) 个,所以构造两条长度为 \(100+1\) 的链,第一条链全是 \(x\) 第二条链全是 \(y\),对于 \(f[i][j]\) 只需要将全是 \(x\) 的链上正数第 \(i\) 个和另一条链上倒数第 \(j\) 个位置连起来,边权为 \(f[i][j]\) 即可。

最后,全 \(x\) 链的第一个位置为 \(S\),另一条链最后一个位置是 \(T\)

#include<cstdio>
const int M=205;
int A,B,f[M][M],d[15][15];
inline int max(const int&a,const int&b){
	return a>b?a:b;
}
inline int min(const int&a,const int&b){
	return a>b?b:a;
}
signed main(){
	scanf("%d%d",&A,&B);for(int i=1;i<=A;++i)for(int j=1;j<=B;++j)scanf("%d",&d[i][j]);
	for(int i=0;i<=100;++i)for(int j=0;j<=100;++j){
		for(int x=1;x<=A;++x)for(int y=1;y<=B;++y)f[i][j]=max(f[i][j],d[x][y]-i*x-j*y);
	}
	for(int x=0;x<=A;++x)for(int y=0;y<=B;++y){
		int mi(100);
		for(int i=0;i<=100;++i)for(int j=0;j<=100;++j)mi=min(mi,f[i][j]+i*x+j*y);
		if(mi!=d[x][y])return printf("Impossible"),0;
	}
	printf("Possible\n202 10401\n");
	for(int i=1;i<=100;++i)printf("%d %d X\n",i,i+1);for(int i=102;i<=201;++i)printf("%d %d Y\n",i,i+1);
	for(int i=0;i<=100;++i)for(int j=0;j<=100;++j)printf("%d %d %d\n",i+1,202-j,f[i][j]);
	printf("1 202");
}
posted @ 2022-08-12 18:30  Prean  阅读(23)  评论(0编辑  收藏  举报
var canShowAdsense=function(){return !!0};