[bzoj3436]小K的农场【差分约束系统】【判负环】

【题目链接】
  http://www.lydsy.com/JudgeOnline/problem.php?id=3436
【题解】
  一道比较裸的差分约束模板题。
  当 opt=1 o p t = 1 时, a a b b 连一条权值为 c − c 的边。
  当 opt=2 o p t = 2 时, b b a a 连一条权值为 c c 的边。
  当 opt=3 o p t = 3 时, a a b b 连一条权值为 0 0 的边, b b a a 连一条权值为 0 0 的边。
  以上所有边的意义为 a+wb a + w ≥ b
  所以跑一边spfa求是否有求负环即可。
  tips:spfa用bfs写TLE,用dfs写能快很多,判断方式是若路径上之前已经出现了这个点,则一定有负环,直接退出。
  

/* --------------
    user Vanisher
    problem bzoj-3436 
----------------*/
# include 
# define    ll      long long
# define    inf     0x3f3f3f3f
# define    N       10010
using namespace std;
int read(){
    int tmp=0, fh=1; char ch=getchar();
    while (ch<'0'||ch>'9'){if (ch=='-') fh=-1; ch=getchar();}
    while (ch>='0'&&ch<='9'){tmp=tmp*10+ch-'0'; ch=getchar();}
    return tmp*fh;
}
int dis[N],use[N],ti[N],q[N],head[N];
struct node{
    int data,next,vote;
}e[N*10];
int place,n,m;
void build(int u, int v, int k){
    e[++place].data=v; e[place].next=head[u]; head[u]=place; e[place].vote=k;
}
/*bool spfa(){
    memset(dis,inf,sizeof(dis));
    memset(use,0,sizeof(use));
    memset(ti,0,sizeof(ti));
    q[1]=0; int pl=1, pr=1; dis[0]=0; use[0]=true; 
    while (pl<=pr){
        int x=q[(pl++)%N];
        for (int ed=head[x]; ed!=0; ed=e[ed].next)
            if (dis[e[ed].data]>dis[x]+e[ed].vote){
                dis[e[ed].data]=dis[x]+e[ed].vote;
                if (use[e[ed].data]==false){
                    ti[e[ed].data]++;
                    if (ti[e[ed].data]>=n) return 1;
                    use[e[ed].data]=true;
                    q[(++pr)%N]=e[ed].data;
                }
            }
        use[x]=false;
    } 
    return 0;
}*/
bool spfa(int x){
    use[x]=true;
    for (int ed=head[x]; ed!=0; ed=e[ed].next)
        if (dis[e[ed].data]>dis[x]+e[ed].vote){
            dis[e[ed].data]=dis[x]+e[ed].vote;
            if (use[e[ed].data]==true) return true;
            if (spfa(e[ed].data)) return true;
        }
    use[x]=false;
    return false;
}
int main(){
    n=read(), m=read();
    int u,v,k;
    for (int i=1; i<=m; i++){
        int opt=read();
        if (opt==1){
            u=read(), v=read(), k=read();
            build(u,v,-k);
        }
        if (opt==2){
            u=read(), v=read(), k=read();
            build(v,u,k);
        }
        if (opt==3){
            u=read(), v=read();
            build(u,v,0);
            build(v,u,0);
        }
    } 
    for (int i=1; i<=n; i++)
        build(0,i,0);
    memset(dis,inf,sizeof(dis));
    dis[0]=0;
    bool flag=spfa(0);
    if (flag==1)
        printf("No\n");
        else printf("Yes\n");
    return 0;
}

你可能感兴趣的:(【差分约束系统】,【判负环】)