差分约束板子

来源:互联网 发布:淘宝网店学校 编辑:程序博客网 时间:2024/06/05 14:43

注意有图的连通性的坑,构造超级原点

不等式求最小值,造 A-B>=C   ---》 B->A=C的边  ,求最长路。

若为A-B>C的形式 构造为A-B>=C+1 从而造边

可以判正环

#include <iostream>#include <stdlib.h>#include <string.h>#include <stdio.h>#include <queue>#include <vector>#include <cmath>#include <stack>using namespace std;const int maxn=10005;typedef long long ll;vector<pair<int ,ll > > vec[maxn];int vis[maxn];int info[maxn];ll dis[maxn];const ll inf=0x3f3f3f3f3f3f3f3f;int n,m;int spfa(int st){    memset(info,0,sizeof(info));    memset(vis,0,sizeof(vis));    for(int i=0;i<=n;i++)    {        vis[i]=0,dis[i]=-inf,info[i]=0;    }    vis[st]=1,dis[st]=0,info[st]=1;    deque<int>q;    q.push_front(st);    int u;    while(!q.empty())    {        u=q.front();        q.pop_front();         vis[u]=0;        for(int i=0; i<vec[u].size(); i++)        {            int v=vec[u][i].first;            ll w=vec[u][i].second;            if( dis[v] < w+dis[u] )            {                dis[v]=w+dis[u];                if(!vis[v])                {                    info[v]++;                    vis[v]=1;                    if(!q.empty()&&dis[v]<dis[q.front()])                        q.push_back(v);                    else                        q.push_front(v);                    if(info[v]>n)                    {                        return 0;                    }                }            }        }    }    return 1;}int main(){    while(~scanf("%d%d",&n,&m) )    {    for(int i=0; i<=maxn; i++)        vec[i].clear();    int u,v;    ll w;    ///造边    /*    for(int i=1;i<=n;i++)    {        scanf("%lld",&w);        vec[i-1].push_back( make_pair(i,0) );        vec[i].push_back(make_pair(i-1,-w));        vec[0].push_back(make_pair(i,0));    }    for(int i=1;i<=m;i++)    {        scanf("%d%d%lld",&u,&v,&w);        vec[u-1].push_back(make_pair(v,w));    }*/    if(spfa(0))    {        printf("%lld\n",dis[n]);    }    else    {         puts("Bad Estimations");    }    }    return 0;}

不等式求最大值,造A-B《=C的不等式  构造B->A ==C的边

若为A-B<C  构造A-B<=C-1 的边即可。

 可以判负环
#include <iostream>#include <stdlib.h>#include <string.h>#include <stdio.h>#include <queue>#include <vector>#include <cmath>#include <stack>using namespace std;const int maxn=100005;vector<pair<int ,double > > vec[maxn];int vis[maxn];int info[maxn];typedef long long ll;lll dis[maxn];const ll inf=0x3f3f3f3f3f3f3f3f;int n,m; int spfa(){    memset(info,0,sizeof(info));    memset(vis,0,sizeof(vis));    for(int i=0;i<=n;i++)    {        dis[i]=inf;     }    vis[0]=1,dis[0]=0,info[0]=1;    stack<int> s;    s.push(0);    int u;    while(!s.empty())    {        u=s.top();        s.pop();              vis[u]=0;        for(int i=0;i<vec[u].size();i++)        {            int v=vec[u][i].first;            ll w=vec[u][i].second;            if( dis[v]>w+dis[u] )            {                dis[v]=w+dis[u];                if(!vis[v])                {                    info[v]++;                    vis[v]=1;                    s.push(v);                    if(info[v]>n)   ///注意负环判断位置                    {                         return 0;                    }                }            }        }    }    return 1;}int main(){    while(~scanf("%d%d",&n,&m))    {        for(int i=0;i<=maxn;i++)            vec[i].clear();            ///造边  注意造超级原点,即为 0->所有边为 0        if(spfa(0))        {            printf("YES\n");        }        else            printf("NO\n");    }}

0 0
原创粉丝点击