1993 小k的农场
差分约束的题一般都是用SPFA进行解决
输入多种不同的路径,差分路径,权值路劲,双向路径
然后判断是否满足最短路性质
#include<iostream>
#include<algorithm>
#include<string>
#include<cstring>
#include<cstdio>
#include<queue>
using namespace std;
const int SIZE=5005;
int n, m, cnt, elast[SIZE], dis[SIZE], num[SIZE];
bool vis[SIZE];
struct edge
{
int to, len, next;
} e[15005];
queue<int> q;
void add (int u, int v, int w) //邻接表
{
e[++cnt].to = v;
e[cnt].len = w;
e[cnt].next = elast[u];
elast[u] = cnt;
}
bool spfa (int x)
{
dis[x] = 0;
q.push(x);
vis[x] = true;
num[x]++;//计算答案
while (!q.empty())
{
int u = q.front();
q.pop();
vis[u] = false;
for (int i = elast[u]; i != 0; i = e[i].next)
if (dis[e[i].to] > dis[u] + e[i].len)
{
dis[e[i].to] = dis[u] + e[i].len;
if (!vis[e[i].to])
{
q.push(e[i].to);
vis[e[i].to] = true;
num[e[i].to]++;//计算答案
if (num[e[i].to] == n + 1)//无解
return false;
}
}
}
return true;
}
int main ()
{
scanf("%d %d", &n, &m);
memset(dis, 0x3f3f3f3f, sizeof(dis));
for (int i = 1; i <= m; i++)
{
int opt;
scanf("%d", &opt);
switch (opt)
{
case 1:
{
int a, b, c;
scanf("%d %d %d", &a, &b, &c);
add(a, b, -c);//差分边
break;
}
case 2:
{
int a, b, c;
scanf("%d %d %d", &a, &b, &c);
add(b, a, c);//权值边
break;
}
case 3:
{
int a, b;
scanf("%d %d", &a, &b);
add(a, b, 0);
add(b, a, 0);//双向边
break;
}
}
}
for (int i = 1; i <= n; i++)
add(n + 1, i, 0);
bool flag = spfa(n + 1);//计算最短路径
if (!flag)
{
printf("No");
return 0;
}
printf("Yes");
return 0;
}