通化邀请赛 I-Difference

来源:互联网 发布:怎么进行网络直播 编辑:程序博客网 时间:2024/04/27 22:47

http://acm.jlu.edu.cn/joj/showproblem.php?pid=2797

这个题目现场赛的时候没过,想得过于简单了。

主要条件如下

(a) |ai| < T for all i and
(b) (vi, vj) in E <=> |ai-aj| >= T,

首先,如过存在边,那么ai和aj必然一正一负。所以第一步就是黑白染色。

之后不妨假设黑色的为正,白色为负,此时条件b中的绝对值号就可以去掉了。对于一堆的大于等于的约束,可以使用差分约束的方法来做。

对于其中的小于T的约束,变成小于等于T-1。如果spfa的时候使用整数的话,此处的T设为一个300+的数字即可。

不擅长图论,代码略长……



#include <iostream>#include <cstdio>#include <cstdlib>#include <cstring>using namespace std;const int intmax=0x3f3f3f3f;//NOTES:intmax#define mem(a, val) memset(a, val, sizeof(a))//memset(const int N = 310;const int T = N;int mat[N][N];int mark[N];int col[N];int cas, n;void fun(int i, int c){    if (col[i] != -1) return;    col[i] = c;    for (int j=0; j<n; ++j){        if (mat[i][j]) fun(j, c^1);    }}int dis[N];int dd[N][N];int q[N*N*2], inq[N], cnt[N];bool spfa(int n){    mem(dis, 0x3f);    int head = 0, tail = 0;    mem(cnt, 0);    mem(inq, 0);    dis[n] = 0;    q[tail++] = n;    inq[n] = 1;    while(head != tail){        int u = q[head ++];        inq[u] = 0;        for (int i=0; i<=n; ++i){            if (dd[u][i] == intmax) continue;            if (dis[u] + dd[u][i] < dis[i]){                dis[i] = dis[u] + dd[u][i];                if (!inq[i]){                    inq[i] = 1;                    q[tail++] = i;                    cnt[i] ++;                    if (cnt[i] > n) return false;                }            }        }    }    return true;}bool judge(int n){    mem(col, 0xff);    mem(mark, 0xff);    for (int i=0; i<n; ++i) fun(i, 0);    for (int i=0; i<n; ++i) for (int j=0; j<n; ++j){        if (mat[i][j] && col[i] == col[j]) return false;    }    mem(dd, 0x3f);    int a, b;    for (int i=0; i<n; ++i){        for (int j=0; j<n; ++j){            if (col[i] == col[j]) continue;            a = i, b = j;            if (col[i] == 1) swap(a, b);            if (mat[a][b]){                dd[a][b] = -T;            }else{                dd[b][a] = T - 1;            }        }    }    for (int i=0; i<n; ++i){        if (col[i] == 0){            dd[i][n] = 0;            dd[n][i] = T - 1;        }else {            dd[n][i] = 0;            dd[i][n] = T - 1;        }    }    return spfa(n);}int main(){    scanf("%d", &cas);    while(cas --){        scanf("%d", &n);        for (int i=0; i<n; ++i) for (int j=0; j<n; ++j){            scanf("%1d", &mat[i][j]);        }        if (judge(n)){            puts("Yes");        }else{            puts("No");        }    }    return 0;}
原创粉丝点击