版权声明:反正也没有人会转,下一个 https://blog.csdn.net/drtlstf/article/details/82811685
Description
给出一有向图,图中每条边都被标上了关系运算符‘<’,‘>’,‘=’。现在要给图中每个顶点标上一个大于等于0,小于等于k的某个整数使所有边上的符号得到满足。若存在这样的k,则求最小的k,若任何k都无法满足则输出NO。
例如下表中最小的k为2。
结点1>结点2
结点2>结点3
结点2>结点4
结点3=结点4
如果存在这样的k,输出最小的k值;否则输出‘NO’。
Input
共二行,第一行有二个空格隔开的整数n和m。n表示G的结点个数,m表示G的边数,其中1<=n<=1000, 0<=m<=10000。全部结点用1到n标出,图中任何二点之间最多只有一条边,且不存在自环。
第二行共有3m个用空格隔开的整数,第3i-2和第3i-1(1<=i<=m)个数表示第i条边的顶点。第3i个数表示第i条边上的符号,其值用集合{-1,0,1}中的数表示:-1表示‘<’, 0 表示‘=’, 1表示‘>’。
Output
仅一行,如无解则输出‘NO’;否则输出最小的k的值。
Sample Input
4 4
1 2 -1 2 3 0 2 4 -1 3 4 -1
Sample Output
2
差分约束比较模板的一道题,求最小值用SPFA最长路.
#include <iostream>
#include <cstring>
#include <queue>
#define SIZE 1010
#define INF 1e+09
using namespace std;
struct edge // 定义一条边的结构体.
{
int to, dis;
};
vector<edge> graph[SIZE];
queue<int> q;
int dis[SIZE], count[SIZE], n;
bool inqueue[SIZE];
void spfa(void) // SPFA最长路
{
int u, v, w, i, res = 0;
for (i = 1; i <= n + 1; ++i)
{
dis[i] = -INF;
}
q.push(0);
inqueue[0] = true;
++count[0];
while (!q.empty())
{
u = q.front();
q.pop();
inqueue[u] = false;
for (i = 0; i < graph[u].size(); ++i)
{
v = graph[u][i].to;
w = graph[u][i].dis;
if (dis[v] < dis[u] + w) // 这里条件换一下就可以了
{
dis[v] = dis[u] + w;
if (!inqueue[v])
{
if (++count[v] >= n) // 存在正环
{
printf("NO");
return;
}
q.push(v);
inqueue[v] = true;
}
}
}
}
printf("%d", dis[n+1]);
return;
}
int main(int argc, char** argv)
{
int m, u, v, w, i;
scanf("%d%d", &n, &m);
while (m--)
{
scanf("%d%d%d", &u, &v, &w);
switch (w) // 建图!
{
case -1:
graph[u].push_back({v, 1});
break;
case 0:
graph[u].push_back({v, 0});
graph[v].push_back({u, 0});
break;
case 1:
graph[v].push_back({u, 1});
break;
}
}
for (i = 1; i <= n; ++i)
{
graph[0].push_back({i, 0});
graph[i].push_back({n + 1, 0});
}
spfa();
return 0;
}