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:b
const 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:b
const 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;
}