传送门
题意:有N头牛,第i头牛一定在第i-1头和第i+1头中间(按照编号从小到大排列)给出两种约束
1. A 到 B 的距离不超过 D
2. A 到 B 的距离小于 D
要求第N头到第一头的距离最远。若无解,输出-1,若无限远,输出-2.
用dis(i)表示从第一头牛到第i头牛的距离,所以
-对于条件1有:dis(A) + D >= dis(B) 连一条从A到B的有向边权值为D(因为最大为D……)
-对于条件2有:dis(A) + D <= dis(B),变形为dis(B) - D >= dis(A),连一条从B到A的有向边权值为-D
又因为i+1要在i的后面,所以有dis(i+1) + 0 >= dis(i),连一条从i+1到i的等于0的边
#include<queue>
#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
const int MAXN = 1005;
const int MAXM = 20005;
struct node
{
int v, w;
node *next;
}Edge[MAXM*2], *Adj[MAXN], *Mcnt = Edge;
void Addedge(int u,int v,int w)
{
node *t = ++Mcnt;
t->v = v;
t->w = w;
t->next = Adj[u];
Adj[u] = t;
}
int n, ml, md, dis[MAXN], cnt, vis[MAXN];
bool inq[MAXN];
bool spfa(int s)
{
memset(dis, 0x3f, sizeof dis);
memset(vis, 0, sizeof vis);
memset(inq, 0, sizeof inq);
dis[s] = 0;
inq[s] = vis[s] = 1;
queue<int> q;
q.push(s);
while(!q.empty())
{
int u = q.front();
q.pop();
inq[u] = 0;
for(node *p = Adj[u]; p; p = p->next)
{
int v = p->v;
if(dis[u] + p->w < dis[v])
{
dis[v] = dis[u] + p->w;
if(!inq[v])
{
q.push(v);
++ vis[v];
inq[v] = 1;
if(vis[v] > 6)return 1;
}
}
}
}
return 0;
}
int main()
{
cin>>n>>ml>>md;
int a, b, d;
for(int i = 1; i <= ml; i ++)
{
cin>>a>>b>>d;
Addedge(a, b, d);
}
for(int i = 1; i <= md; i ++)
{
cin>>a>>b>>d;
Addedge(b, a, -d);
}
for(int i = 1; i <= n-1; i ++)
Addedge(i + 1, i, 0);
if(spfa(1))
printf("-1\n");
else if(dis[n] != 0x3f3f3f3f) printf("%d\n", dis[n]);
else printf("-2");
return 0;
}
版权声明:请随意转载O(∩_∩)O
原文:http://blog.csdn.net/gengmingrui/article/details/47427891