差分约束系统专题

来源:互联网 发布:sql 微整型 编辑:程序博客网 时间:2024/06/05 17:42

1、教程
书籍:算法导论p370、黑书
论文:http://wenku.baidu.com/view/c37d3486bceb19e8b8f6baae.html
博客:http://www.cnblogs.com/wangyaohui/articles/2134040.html
http://www.cppblog.com/mythit/archive/2009/06/04/86756.html
http://www.cnblogs.com/litstrong/archive/2010/08/08/1795268.html
(先这些,找到好的再换)
2、一些题目
hdu:1384 1529 1531 1534 3440 3592 3666

poj:1201 1275 1364 2983 3159 3169 
3、解题报告

http://972169909-qq-com.iteye.com/blog/1185527

http://blog.csdn.net/l04205613/article/details/6660930
poj1201 & hdu1384
先定义s[i+1]表示0-i中选的个数,于是
1、题意:[ai,bi]中至少ci个可以表示为s[bi+1]-s[ai]>=ci 
2、定义:1>=s[i+1]-s[i]>=0,也就是i选与不选两种情况
最终s[max+1]-s[min]即为所求

差分约束系统有求最长路,最短路两种方式
1、最长路:s[bi+1]-s[ai]>=ci
2、最短路:s[ai]-s[bi+1]<=-ci

hdu 1529 & poj1275
x[i] 表示第i时刻选定的人数
n[i] 表示第i时刻可选的人数
r[i] 表示第i时刻需要的人数

x[i] <= n[i]
x[i]+x[i-1]+...+x[i-7] >= r[i]

令s[i]=x[0]+x[1]+...+x[i]

0<=s[i]-s[i-1]<=n[i], i=1,2..23
s[0]<=n[0]
s[i]-s[i-8]>=r[i], i=8,9..23
s[23]+s[i]-s[i+16]>=r[i], i=0,1..7

整理得
s[i]-s[i-1]>=0, i=1,2..23
s[i-1]-s[i]>=-n[i], i=1,2..23
s[0]>=-n[0]
s[i]-s[i-8]>=r[i] , i=8,9..23
s[i]-s[i+16]>=r[i]-s[23], i=0,1..7

求min(s[23])

 

代码1:

#include<cstdio>#include<cstring>#include<climits>#include<iostream>#include<queue>#include<vector>using namespace std;#define min(a,b) a<b?a:b#define max(a,b) a>b?a:bconst int N = 51000;struct node{ int v, x; };vector<node> edg[N];int vis[N], tim[N], dis[N];queue<int> q;int s, t, o, n;void input(){    node tmp;    int u, v, x;    for(x=0; x<N; ++x) edg[x].clear();    s=INT_MAX; t=INT_MIN;    // add input edge    while(n--)    {        scanf("%d%d%d", &u, &v, &x);        s=min(s, u); t=max(t, v);        tmp.v=v+1; tmp.x=x;        edg[u].push_back(tmp);    }    t++;    // add -1 edge    for(u=t; u>s; --u)    {        tmp.v=u-1; tmp.x=-1;        edg[u].push_back(tmp);    }    // add 0 edge    for(u=s; u<t; ++u)    {        tmp.v=u+1; tmp.x=0;        edg[u].push_back(tmp);    }}void spfa(){    int i, u, v, x, m;    memset(vis, 0, sizeof(vis));    for(i=s; i<=t; ++i) dis[i]=-INT_MAX;    while(!q.empty()) q.pop();    dis[s]=0; q.push(s); vis[s]=1;    while(!q.empty())    {        u=q.front(); q.pop(); vis[u]=0;        m=edg[u].size();        for(i=0; i<m; ++i)        {            v=edg[u][i].v;            x=edg[u][i].x;            if(dis[v]<dis[u]+x)            {                dis[v]=dis[u]+x;                if(!vis[v])                {                    vis[v]=1; q.push(v);                }            }        }    }    printf("%d\n", dis[t]-dis[s]);}int main(){    while(~scanf("%d",&n))    {        input();        spfa();    }    return 0;}


代码2:

#include<cstdio>#include<cstring>#include<climits>#include<iostream>#include<queue>#include<vector>using namespace std;#define min(a,b) a<b?a:b#define max(a,b) a>b?a:bconst int N = 51000;struct node{ int v, x; };vector<node> edg[N];int vis[N], tim[N], dis[N];queue<int> q;int s, t, o, n;void input(){    node tmp;    int u, v, x;    for(x=0; x<N; ++x) edg[x].clear();    s=INT_MAX; t=INT_MIN;    // add input edge    while(n--)    {        scanf("%d%d%d", &v, &u, &x);        u++; s=min(s, v); t=max(t, u);        tmp.v=v; tmp.x=-x;        edg[u].push_back(tmp);    }    // add 0 edge    for(u=t; u>s; --u)    {        tmp.v=u-1; tmp.x=0;        edg[u].push_back(tmp);    }    // add 1 edge    for(u=s; u<t; ++u)    {        tmp.v=u+1; tmp.x=1;        edg[u].push_back(tmp);    }    u=o=t+1; tmp.x=0;    // add o-> x    for(x=s; x<=t; ++x)    {        tmp.v=x; edg[u].push_back(tmp);    }    n=t-s+2;}void spfa(){    int i, u, v, x, m;    memset(vis, 0, sizeof(vis));    memset(tim, 0, sizeof(tim));    for(i=s; i<=t; ++i) dis[i]=INT_MAX;    while(!q.empty()) q.pop();    dis[o]=0; q.push(o); vis[o]=tim[o]=1;    while(!q.empty())    {        u=q.front(); q.pop(); vis[u]=0;        m=edg[u].size();        for(i=0; i<m; ++i)        {            v=edg[u][i].v;            x=edg[u][i].x;            if(dis[v]>dis[u]+x)            {                dis[v]=dis[u]+x;                if(!vis[v])                {                    vis[v]=1; q.push(v); tim[v]++;                     if(tim[v]>n)                         while(!q.empty()) q.pop();                }            }        }    }    printf("%d\n", dis[t]-dis[s]);}int main(){    while(~scanf("%d",&n))    {        input();        spfa();    }    return 0;}


原创粉丝点击