题解 AT3877 【[ARC089C] GraphXY】
在【有趣的思维题】里看到了这道题。
题意:
给出一个\(A\times B\)的矩阵,其中第i行第j列元素为\(d_{i,j}\),试构造一个有向图,满足:
-
有向图点数\(\le 300\)
-
没有重边和自环
-
图中边有边权,边权\(\in [0,100]\)且是正整数。或者是未知数X或者Y
-
对于所有\(x \in [1,A] \ y\in[1,B]\),满足未知数\(X=x,Y=y\)时,图中s到t的最短路为\(d_{x,y}\)
看清楚题目了,睁大眼睛。s和t是自己选定的,x和y是在区间内变化的,再读一遍题意。
分析:
当 \(s\) 与 \(t\) 之间的路径上有 \(i\) 个\(x\) ,\(j\) 个 \(y\) ,设 \(f_{i,j}\) 表示此时路径上其余边的最小可能长度。
\(d_{x,y}\ge ix+jy+f_{i,j}\) 。
有:\(d_{x,y}=\min \{ix+jy+f_{i,j}\}\)
\(d_{x,y}-ix-jy \le f_{i,j}\)
\(f_{i,j}=\max \{d_{x,y}-ix-jy\}\)
尝试构造一种情况,
连两条长度为 \(100\) ,有 \(101\) 个点的链,一条链所有边权为 \(X\) ,另一条链所有边权为 \(Y\)
设 \(s=1,t=202\)
\(X\) 链的第 \(i\) 个节点和 \(Y\) 链的倒数第 \(j\) 个节点间连一条边权 \(f_{i,j}\) 的边。
如果 \(d_{x,y} \neq \min \{ix+jy+f_{i,j}\}\) 则是无解情况。
否则输出答案。
#include<bits/stdc++.h>
using namespace std;
const int inf=0x3f3f3f3f,N=310;
int n,m,f[N][N],d[N][N];
int bmin(int a,int b){ return (a<b)?a:b;}
int bmax(int a,int b){ return (a<b)?b:a;}
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++) for(int j=1;j<=m;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<=n;x++) for(int y=1;y<=m;y++)
f[i][j]=bmax(f[i][j],d[x][y]-i*x-j*y);
for(int x=1;x<=n;x++) for(int y=1;y<=m;y++){
int mn=inf;
for(int i=0;i<=100;i++) for(int j=0;j<=100;j++)
mn=bmin(mn,f[i][j]+i*x+j*y);
if(mn!=d[x][y]){ puts("Impossible"); return 0; }
}
puts("Possible"); printf("202 10401\n");
for(int i=1;i<=100;i++) printf("%d %d X\n",i,i+1);
for(int i=102;i<202;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]);
puts("1 202");
return 0;
}
QwQwQ