差分约束系统介绍:
http://blog.youkuaiyun.com/liuzhushiqiang/article/details/9344919分析:
给除N个点,ML表示AB间距离小于D,MD表示AB间距离大于D,建图用差分约束模板即可题解
1.建图:
struct node
{
int v, w, next;
}edge[eMax];
int n, k, edgeHead[nMax], dis[nMax], sum[nMax];
int stack[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 ++;
}
int ml, md;
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);
2.SPFA检测负权判断有无解:
bool spfa()
{
for(int i = 2; i <= n; i ++)
dis[i] = inf;
dis[1] = 0;
int top = 0; // 堆栈实现spfa。
stack[++ top] = 1;
vis[1] = true;
while(top)
{
int u = stack[top --];
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;
stack[++ top] = v;
if(++ sum[v] > n) // 有一个点进栈超过n次,则说明有负环。
return true;
}
}
}
}
return false;
}
if(spfa())
printf("-1\n"); // 有负环存在,方程组无解。
else if(dis[n] == inf)
printf("-2\n"); // 距离为inf。
else printf("%d\n", dis[n]); // 有解且距离在一个范围内。
return 0;
- 参考代码:
#include<iostream>
#include <cstdio>
using namespace std;
const int nMax = 1005;
const int eMax = 21005;
const int inf = 0xffffff;
struct node
{
int v, w, next;
}edge[eMax];
int n, k, edgeHead[nMax], dis[nMax], sum[nMax];
int stack[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()
{
for(int i = 2; i <= n; i ++)
dis[i] = inf;
dis[1] = 0;
int top = 0; // 堆栈实现spfa。
stack[++ top] = 1;
vis[1] = true;
while(top)
{
int u = stack[top --];
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;
stack[++ top] = v;
if(++ sum[v] > n) // 有一个点进栈超过n次,则说明有负环。
return true;
}
}
}
}
return false;
}
int main()
{
int ml, md;
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"); // 距离为inf。
else printf("%d\n", dis[n]); // 有解且距离在一个范围内。
return 0;
}