Time Limit: 1000MS |
| Memory Limit: 65536K |
Total Submissions: 8975 |
| Accepted: 4308 |
Description
Some cows like each other and want to be within a certain distance of each other in line. Some really dislike each other and want to be separated by at least a certain distance. A list of ML (1 <= ML <= 10,000) constraints describes which cows like each other and the maximum distance by which they may be separated; a subsequent list of MD constraints (1 <= MD <= 10,000) tells which cows dislike each other and the minimum distance by which they must be separated.
Your job is to compute, if possible, the maximum possible distance between cow 1 and cow N that satisfies the distance constraints.
Input
Lines 2..ML+1: Each line contains three space-separated positive integers: A, B, and D, with 1 <= A < B <= N. Cows A and B must be at most D (1 <= D <= 1,000,000) apart.
Lines ML+2..ML+MD+1: Each line contains three space-separated positive integers: A, B, and D, with 1 <= A < B <= N. Cows A and B must be at least D (1 <= D <= 1,000,000) apart.
Output
Sample Input
4 2 1
1 3 10
2 4 20
2 3 3
Sample Output
27
Hint
There are 4 cows. Cows #1 and #3 must be no more than 10 units apart, cows #2 and #4 must be no more than 20 units apart, and cows #2 and #3 dislike each other and must be no fewer than 3 units apart.
The best layout, in terms of coordinates on a number line, is to put cow #1 at 0, cow #2 at 7, cow #3 at 10, and cow #4 at 27.
题意:有N头牛,编号1~N。按照编号顺序排成一排。在他们之间有些牛关系比较好,所以希望彼此之间不超过一定距离,给出ML表示有ML对(A,B,D),表示A与B间距离最大是D。也有一些牛关系非常不好,它们之间的距离也必须要大于一定距离。给出DL表示有DL对(A,B,D),表示A与B间距离最小是D。此外可能有多头牛站在同一个位置。求1号牛到N号牛之间的距离。如果不存在任何一种满足条件的排列方式则输出-1。无限大的情况输出-2。
题解:差分约束问题,转化为最短路求解。设第i头牛站在dis[i]的位置。要求牛按顺序站立,我们可以知道dis[i+1]>=dis[i],从i+1到i的权值为0。根据给出的关系好的ML条信息,可以得到dis[MA]+MD>=dis[MB],这样就从MA到MB的权值为MD(注意:是单向带全图)。根据给出的关系差的DL条信息,可以得到dis[DA]+DD<=dis[DB],这样就从DB到DA的权值为DD。根据这三个约束条件(不等式),建图。1号牛到N号牛的最长距离就是图中的最短路径。但图中可能含有负权环,所以不能用dijsktra算法。SPFA算法能判断负环。有负环的就表示不存在任何一种满足条件的排列。
具体代码如下:
#include<cstdio>
#include<cstring>
#include<queue>
#define maxn 1010
#define maxm 50010
#define INF 0x3f3f3f
using namespace std;
int dis[maxn],visit[maxn],mark[maxn],top,n;
int head[maxn];
struct node
{
int to,val,next;
}edge[maxm];
void add(int a,int b,int c)
{
edge[top].to=b;
edge[top].val=c;
edge[top].next=head[a];
head[a]=top++;
}
void spfa()
{
int i,v,u,mark[maxn];
queue<int>q;
for(i=1;i<=n;++i)
{
dis[i]=INF;
visit[i]=0;
mark[i]=0;
}
q.push(1);
dis[1]=0;
visit[1]=1;
mark[1]=1;//记录入队列的次数
while(!q.empty())
{
v=q.front();
q.pop();
visit[v]=0;
for(i=head[v];i!=-1;i=edge[i].next)
{
u=edge[i].to;
if(dis[u]>dis[v]+edge[i].val)
{
dis[u]=dis[v]+edge[i].val;
if(!visit[u])
{
visit[u]=1;
mark[u]++;
q.push(u);
if(mark[u]>=n)//存在负环
{
printf("-1\n");
return ;
}
}
}
}
}
if(dis[n]==INF)//表示最大距离可以无限大
printf("-2\n");
else
printf("%d\n",dis[n]);
}
int main()
{
int ML,MD,u,v,d,i;
while(scanf("%d%d%d",&n,&ML,&MD)!=EOF)
{
top=0;
memset(head,-1,sizeof(head));
for(i=1;i<n;++i)//连接前后牛的边,从i+1到i的边权
add(i+1,i,0);
while(ML--)
{
scanf("%d%d%d",&v,&u,&d);
add(v,u,d);
}
while(MD--)
{
scanf("%d%d%d",&v,&u,&d);
add(u,v,-d);
}
spfa();
}
return 0;
}