其他分享
首页 > 其他分享> > Atcoder Regular Contest 089E - GraphXY题解

Atcoder Regular Contest 089E - GraphXY题解

作者:互联网

题意:给你一个未知的图,中间有一些边是定值,另一些边可能为X,也可能为Y,令\(d_{x,y}\)为当所有的\(X=x,Y=y\)时,从S到T的最短路径长度。给你所有的\(d_{x,y} (1 \le x,y \le 10)\),请构造出这样的一个图,图中点数不得超过\(300\),若无解,请输出"Impossible"(不含双引号),否则,请输出"Possible"(不含双引号),并在下一行输出节点个数与边数,接下来输出所有的边及边长(是一个常数或'X'或'Y'),最后输出S和T。
题解:令\(f[i][j]\)表示从S到T的路径上有i个x和j个y时其余边的最小可能长度,若我们已知\(f[i][j]\),则可以推出\(d[x][y]=min\{f[i][j]+i*x+j*y\}\),那么对该式进行移项,得出\(f[i][j]=max\{d[x][y]-i*x-j*y\}\),但该\(f[i][j]\)不一定符合条件,重新判断,若不符合则该情况一定无解,否则一定可以构造出一解。
考虑如何构造:连两条长度为100的链(显然,长度更长毫无意义),一条链所有边权为X,另一条链所有边权为Y,那么对于每一个\(f[i][j]\),可以在X链上的第\(i\)个节点和Y链上的倒数第\(j\)个节点间连一条长度为\(f[i][j]\)的边。即可构造方案。
code:

#include <cstdio>
#include <cstring>
#define Maxn 300
#define Maxk 10
#define Inf 0x3f3f3f3f
int f[Maxn+5][Maxn+5];
int d[Maxk+5][Maxk+5];
//f[i][j]表示从S到T的路径上有i个x和j个y时其余边的最小可能长度 
//d[x][y]=min{f[i][j]+i*x+j*y}
//f[i][j]=max{d[x][y]-i*x-j*y}
int mx(int a,int b){
    return a>b?a:b;
}
int mn(int a,int b){
    return a<b?a:b;
}
struct Edge{
    int u,v,w;
}edge[Maxn*Maxn+5];
int n,m;
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]=mx(f[i][j],d[x][y]-i*x-j*y);
                }
            }
        }
    }
    int now;
    for(int x=1;x<=n;x++){
        for(int y=1;y<=m;y++){
            now=Inf;
            for(int i=0;i<=100;i++){
                for(int j=0;j<=100;j++){
                    now=mn(now,f[i][j]+i*x+j*y);
                }
            }
            if(now!=d[x][y]){
                puts("Impossible");
                return 0;
            }
        }
    }
    puts("Possible");
    puts("202 10401");
    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;
}

标签:Atcoder,089E,输出,int,题解,Maxk,Maxn,长度,define
来源: https://www.cnblogs.com/withhope/p/11740792.html