BZOJ 3436 小K的农场

来源:互联网 发布:微信支付接口开发 php 编辑:程序博客网 时间:2024/05/28 05:15

差分约束

裸的差分约束,没什么好说的。大概说一下DFS版的SPFA为什么可以找得到负环。
前提是每一个点都被访问到至少一次。

一个负环上一定存在一个点p,使得从p开始绕着环走出来的距离总是负数。

反证,即假设每一个点出发绕环走都存在一次让走的距离为正,则可以构造一种方案使得可以无限次绕环走而总是非负,显然与负环矛盾。

然后随便设一个源点向每一个点连边判SPFA负环即可。

#include<bits/stdc++.h>#define N 10005using namespace std;namespace runzhe2000{    int n, m, last[N], ecnt, dis[N], inq[N];    struct edge{int next, to, val;}e[N<<2];    void addedge(int a, int b, int c)    {        e[++ecnt] = (edge){last[a], b, c};        last[a] = ecnt;    }    void SPFA(int x)    {        inq[x] = 1;        for(int i = last[x]; i; i = e[i].next)        {            int y = e[i].to;             if(dis[x] + e[i].val < dis[y])            {                dis[y] = dis[x] + e[i].val;                if(inq[y]){puts("No");exit(0);}                SPFA(y);            }        }        inq[x] = 0;    }    void main()    {        scanf("%d%d",&n,&m);        for(int i = 1; i <= m; i++)        {            int type, a, b, c; scanf("%d",&type);            if(type == 1)            {                scanf("%d%d%d",&a,&b,&c);                addedge(a, b, -c);            }            else if(type == 2)            {                scanf("%d%d%d",&a,&b,&c);                addedge(b, a, c);            }            else            {                scanf("%d%d",&a,&b);                addedge(a, b ,0); addedge(b, a, 0);            }        }        for(int i = 1; i <= n; i++) addedge(n+1, i, 0);        memset(dis,63,sizeof(dis)); dis[n+1] = 0; SPFA(n+1); puts("Yes");    }}int main(){    runzhe2000::main();}
0 0
原创粉丝点击