#差分约束系统#CodeChef Digit Matrix&洛谷 7515 [省选联考 2021 A 卷] 矩阵游戏


洛谷传送门
DGMATRIX


分析

先任意构造出一个不一定满足值域的矩阵,现在只需要满足值域就可以了。

可以发现,给一行或一列依次加一减一2*2矩阵的和仍然不变,并且如果有解一定能构造出一组方案。

因为第一行和第一列如果确定,所以只要通过这样的加一减一,其它位置就能确定。

设行的选择为 \(dx[i]\),列的选择为 \(dy[j]\),那么就要满足 \(0\leq a[i][j]+dx[i]+dy[j]\leq 10^6\)

可是这样的加法好像也挺难做的,能不能强制让一个为加,一个为减,这是可行的,将矩阵黑白染色。

如果 \(i\)\(j\) 奇偶性不同,那么 \(dy[j]-dx[i]\leq M-a[i][j],dx[i]-dy[j]\leq a[i][j]\)

同奇同偶的情况正好将 \(dx[i]\)\(dy[j]\) 调换即可,跑一遍最短路如果有负环那么无解,否则同样按照奇偶性输出方案即可。


代码(矩阵游戏)

#include 
#include 
#include 
#define rr register
using namespace std;
const int N=301,M=1000000; dequeq;
struct node{int y,w,next;}e[N*N<<1]; long long dis[N<<1];
int cnt[N<<1],et,as[N<<1],v[N<<1],a[N][N],n,m,flag;
inline signed iut(){
	rr int ans=0; rr char c=getchar();
	while (!isdigit(c)) c=getchar();
	while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
	return ans;
}
inline void print(int ans){
	if (ans>9) print(ans/10);
	putchar(ans%10+48);
}
inline void add(int x,int y,int w){
	e[++et]=(node){y,w,as[x]},as[x]=et;
}
signed main(){
	for (rr int T=iut();T;--T){
		n=iut(),m=iut(),et=0;
		for (rr int i=1;i<=n+m;++i) dis[i]=1e15;
		for (rr int i=1;i<=n+m;++i) as[i]=cnt[i]=v[i]=0;
		for (rr int i=1;idis[x]+e[i].w){
				dis[e[i].y]=dis[x]+e[i].w;
				if (!v[e[i].y]){
					v[e[i].y]=1;
					if (!q.empty()&&dis[e[i].y]

代码(DGMATRIX)

#include 
#include 
#include 
using namespace std;
const int N=111,M=9; dequeq;
struct node{int y,w,next;}e[N*N<<1];
int et,as[N<<1],v[N<<1],dis[N<<1],a[N][N],n,m;
int iut(){
	int ans=0; char c=getchar();
	while (!isdigit(c)) c=getchar();
	while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
	return ans;
}
void print(int ans){
	if (ans>9) print(ans/10);
	putchar(ans%10+48);
}
void add(int x,int y,int w){
	e[++et]=(node){y,w,as[x]},as[x]=et;
}
int main(){
	n=iut()+1;
	for (int i=1;i<=n*2;++i) dis[i]=0x3f3f3f3f;
	for (int i=1;idis[x]+e[i].w){
			dis[e[i].y]=dis[x]+e[i].w;
			if (!v[e[i].y]){
				v[e[i].y]=1;
				if (!q.empty()&&dis[e[i].y]

相关