Luogu P1993 小 K 的农场

  其实很早以前就打好了,但一直忘记写了。

  也就是差分约束的模板题。

  关于差分约束,也就是用来求关于一些不等式互相约束算出最优解。

  推荐一个讲的很好的博客:http://www.cppblog.com/menjitianya/archive/2015/11/19/212292.html

  可以通过一个三角形不等式来搞一下:

  B - A <= c      (1)

  C - B <= a      (2)
  C - A <= b      (3)
  如果我们想要知道C - A的最大值,通过(1) + (2),可以得到 C - A <= a + c,所以这个问题其实就是求min{b, a+c}。
  所以这题只需要转换一下不等式,用SPFA来判负环(用DFS比较快)
  CODE
#include<cstdio>
#include<cstring>
using namespace std;
const int N=20005;
struct data
{
    int to,next,v;
}e[N];
int head[N],dis[N],n,m,opt,i,j,x,y,z,k,h,t;
bool flag=0,vis[N];
inline void read(int &x)
{
    x=0; char ch=getchar();
    while (ch<'0'||ch>'9') ch=getchar();
    while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
}
inline void add(int x,int y,int z)
{
    e[++k].to=y; e[k].v=z; e[k].next=head[x]; head[x]=k;
}
inline void SPFA(int k)
{
    vis[k]=1;
    for (int i=head[k];i!=-1;i=e[i].next)
    if (dis[e[i].to]>dis[k]+e[i].v) 
    {
        if (vis[e[i].to]) { flag=1; return; }  else dis[e[i].to]=dis[k]+e[i].v,SPFA(e[i].to);
    }
    vis[k]=0;
}
int main()
{
    read(n); read(m);
    memset(e,-1,sizeof(e));
    memset(head,-1,sizeof(head));
    for (i=1;i<=m;++i)
    {
        read(opt);
        if (opt==1) read(x),read(y),read(z),add(x,y,-z);
        if (opt==2) read(x),read(y),read(z),add(y,x,z);
        if (opt==3) read(x),read(y),add(x,y,0),add(y,x,0);
    }
    for (i=1;i<=n;++i)
    {
        if (flag) break;
        memset(dis,0,sizeof(dis));
        SPFA(i);
    }
    if (flag) puts("No"); else puts("Yes");
    return 0;
}

 

  
posted @ 2018-03-09 13:20  空気力学の詩  阅读(220)  评论(1编辑  收藏  举报