大家应该都会求最短路了吧。不会的去补补再来看。树形dp初步暂时不更了,留了两个大坑,而且还有几个知识点没说也留到下次再补。差分约束应该算是比较容易的内容,就已Poj上的Layout作为例题,网址在此:http://poj.org/problem?id=3169,戳Layout可传送!!!
翻译版本:
题目描述
输入
第1行,3个整数,N,ML,MD
第2至ML+1行,3个整数,A, B, D,其中1 <= A < B <= N. 牛A,B距离最多为D (1 <= D <= 1,000,000)
第ML+2至ML+MD+1行,三个整数,A, B, D, 其中 1 <= A < B <= N. 牛A,B距离最少为D (1 <= D <= 1,000,000)
输出
一个整数
如果在上述条件下,奶牛站不成一排,则输出"-1",如果能站成一排,但是第1头牛~
第N头牛的距离无限远,则输出"-2",如果满足条件,并且第1头牛~第N头牛之间存在实际距离,则输出第1头牛~到第N头牛之间的能达到的最远距离。
样例输入
4 2 1
1 3 10
2 4 20
2 3 3
样例输出
27
zyy:裸题,裸题!!!
选它就是因为它是裸题,心情不好滚一边去差分约束为什么要用到最短路呢?
我们先看看样例:
先用一个数组记录第一头牛到第j头牛的距离。
通过样例可以知道:
d[3]-d[1]<=10
d[4]-d[2]<=20
d[3]-d[2]>=3
通过移项和一些处理后可以知道:
d[3]<=10+d[1]
d[4]<=20+d[2]
d[2]<=-3+d[3]
大家都知道求不等式解的范围。如果要求最大值,不等号右边的数就要最小的如:
x<=4
x<=2
解集就是:x<=2
所以最大值为2
所以这里要取最小的值
而求最短路径时也要用到一个不等式:
for(int i=p[u];~i;i=b[i].next)
if(dis[u]+b[i].w<dis[b[i].v])
{
dis[b[i].v]=dis[u]+b[i].w;
if(!used[b[i].v])
{
a.push(b[i].v);
used[b[i].v]=1;
uses[b[i].v]++;
if(uses[b[i].v]>=n)
{
printf("-1\n");
return;
}
}
}
是不是很像,其实它们本质上是一致的,又因为求最大所以d[j]要最小,反之。
所以这道题就做出来了。
代码如下:
#include<cstdio>
#include<cstring>
#include<queue>
#define MAXN 200000+10
using namespace std;
struct edge
{
int v,w,next;
};
edge b[MAXN];
queue<int> a;
bool used[10001];
int uses[10001],p[10001],dis[10001],n,x1,x2,num;
int read()
{
char c=getchar();
while(c<'0'||c>'9'){c=getchar();}
int x=0;
while(c>='0'&&c<='9'){
x=x*10+c-'0';
c=getchar();
}
return x;
}
void init()
{
memset(uses,0,sizeof(uses));
memset(p,-1,sizeof(p));
for(int i=1;i<=n;i++)
dis[i]=0x7fffffff;
num=0;
}
void SPFA()
{
a.push(1);
used[1]=1;
uses[1]++;
dis[1]=0;
while(!a.empty())
{
int u=a.front();
for(int i=p[u];~i;i=b[i].next)
if(dis[u]+b[i].w<dis[b[i].v])
{
dis[b[i].v]=dis[u]+b[i].w;
if(!used[b[i].v])
{
a.push(b[i].v);
used[b[i].v]=1;
uses[b[i].v]++;
if(uses[b[i].v]>=n)
{
printf("-1\n");
return;
}
}
}
a.pop();
used[u]=0;
}
if(dis[n]==0x7fffffff)printf("-2\n");
else printf("%d\n",dis[n]);
}
int main()
{
n=read();
x1=read();
x2=read();
init();
for(int i=1;i<=x1;i++)
{
int u,v,w;
u=read(),v=read(),w=read();
b[++num].v=v;
b[num].w=w;
b[num].next=p[u];
p[u]=num;
}
for(int i=1;i<=x2;i++)
{
int u,v,w;
u=read(),v=read(),w=read();
b[++num].v=u;
b[num].w=-w;
b[num].next=p[v];
p[v]=num;
}
SPFA();
return 0;
}
在 hdu上还有另一道与它类似,点击"hdu"传送。