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");
}