题意:n头牛编号为1到n,按照编号的顺序排成一列,每两头牛的之间的距离 >= 0。这些牛的距离存在着一些约束关系:1.有ml组(u, v, w)的约束关系,表示牛[u]和牛[v]之间的距离必须 <= w。2.有md组(u, v, w)的约束关系,表示牛[u]和牛[v]之间的距离必须 >= w。问如果这n头无法排成队伍,则输出-1,如果牛[1]和牛[n]的距离可以无限远,则输出-2,否则则输出牛[1]和牛[n]之间的最大距离。
思路:挖掘隐含的约束条件:每两头牛的之间的距离 >= 0加入到差分约束的系统中去。
#include <iostream>
#include <string.h>
#include <stdio.h>
using namespace std;
const int nMax = 21005;
const int inf = 0xffffff;
struct node
{
int v, w, next;
} edge[nMax];
int n, m, k, edgeHead[nMax], dis[nMax], sum[nMax];
int queue[nMax];
bool vis[nMax];
void add_edge(int u, int v, int w)
{
edge[k].v = v;
edge[k].w = w;
edge[k].next = edgeHead[u];
edgeHead[u] = k ++;
}
bool spfa()
{
memset(sum,0,sizeof(sum));
memset(vis,0,sizeof(vis));
int head = 0, tail = 1;
for(int i = 0; i <= n; i ++)
dis[i] = inf;//最大值时inf,下为>号,最小值时-inf,下为<号
dis[1] = 0;
queue[0] = 1;
while(tail != head) // 循环队列实现。
{
int u = queue[head];
vis[u] = false;
for(int p = edgeHead[u]; p != 0; p = edge[p].next)
{
int v = edge[p].v;
if(dis[v] > dis[u] + edge[p].w) //最大值时为>号,最小值时为<号
{
dis[v] = dis[u] + edge[p].w;
if(!vis[v])
{
vis[v] = true;
queue[tail ++] = v;
if(tail == nMax) tail = 0;// 循环队列实现。
if(++sum[v] > n) return true;
}
}
}
head ++;
if(head == nMax) head = 0;// 循环队列实现。
}
return false;
}
int main()
{
int ml, md;
memset(edgeHead, 0, sizeof(edgeHead));
scanf("%d%d%d", &n, &ml, &md);
k = 1;
int u, v, w;
while(ml --)
{
scanf("%d%d%d", &u, &v, &w);
add_edge(u, v, w);
}
while(md --)
{
scanf("%d%d%d", &v, &u, &w);
add_edge(u, v, -w);
}
for(int i = 1; i < n; i ++)
add_edge(i + 1, i, 0);
if(spfa()) printf("-1\n");
else if(dis[n] == inf) printf("-2\n");
else printf("%d\n", dis[n]);
return 0;
}
/*测试:
Sample Input
4 2 1
1 3 10
2 4 20
2 3 3
Sample Output
27
*/