Gym - 101611G - 差分约束系统

题目链接:https://vjudge.net/problem/Gym-101611G

 

解题思路;

解法一;

判断列上横值相加是否为0和横上列值相加是否为0,如果全是则有解,否则无解,

如果列上横值相加等于0,那么就说明可以把这一列的所有横值都变为0.

假设一列的横值为x1,x2,x3....那么在此列的第一个行设置风力为-x1,那么第一个值就变为0,x2则需加上相反数也就是x1,此时x2变为x1+x2,,然后再将第二行风力设为-x1-x2以此类推最后累加是0才能把所有的都变为0.

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int mx = 5e2+5;
#define fi first
#define se second
int n,m;
ll r[mx][mx],c[mx][mx];
bool check()
{
	for(int j=1;j<=m;j++){
		ll ret = 0;
		for(int i=1;i<=n;i++){
			ret += r[i][j];
		}
		if(ret!=0) return 0;
	}
	for(int i=1;i<=n;i++){
		ll ret = 0;
		for(int j=1;j<=m;j++){
			ret += c[i][j];
		}
		if(ret!=0) return 0;
	}
	return 1;
}
int main(){
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++){
			scanf("%lld",r[i]+j);
			scanf("%lld",c[i]+j);
		}
	}
	if(check()) puts("Yes");
	else puts("No");
	return 0;
}

解法2:

如果我们令f[i][j]表示第i行第j列的格子的风力,那么存在有:

 

                                                             ri[i][j]=f[i][j-1]−f[i][j](c[i][j]同理)

将一个等式变为两个不等式做差分约束系统 

保证由任意路径得来的f[i][j]都相同即是有解

#include <cstdio>
typedef long long ll;
const int mx = 5e2 + 10, N = mx * mx, M = N * 8;
int h[N], p[M], v[M], w[M], tot = 0;
int vis[N], id[mx][mx], cnt = 0;
int r[mx][mx], c[mx][mx];
ll f[N];
void add(int a, int b, int c) {
    p[++tot] = h[a]; 
	v[tot] = b; 
	w[tot] = c; 
	h[a] = tot;
}

bool dfs(int x, ll now) {
    if (vis[x]) {
        return f[x] == now;
    }
    vis[x] = 1;
    f[x] = now;
    for (int i = h[x]; i; i = p[i])
        if (!dfs(v[i], now + w[i]))
            return 0;

    return 1;
}

int main() {
    int n, m, i, j;
    scanf("%d%d", &n, &m);
    for (i = 0; i < n; ++i)
        for (j = 0; j < m; ++j) {
            scanf("%d%d", &r[i][j], &c[i][j]);
            id[i][j] = cnt++;
        }
    for (i = 0; i < n; ++i)
        for (j = 0; j < m; ++j) {
            int u = id[i][j];
            int v = id[(i - 1 + n) % n][j];
            add(u, v, r[i][j]);
           // add(v, u, -r[i][j]);

            v = id[i][(j - 1 + m) % m];
            add(v, u, c[i][j]);
           // add(u, v, -c[i][j]);
        }
    if (!dfs(0, 0)) return puts("No");
    return puts("Yes");
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值