差分约束系统:
对于一个不等式
a−b<=c
,建立一条从b到a的权值为c的边,然后求最短路,得到最大值。
对于一个不等式
a−b>=c
,建立一条从b到a的权值为c的边,然后求最长路,得到最小值。
如果有负环的话就无解。
题解:
对于1-N的每一头牛都满足:
a[i]−a[i+1]<=0
对于关系好的牛来说:(假设i < j)
a[j]−a[i]<=k
对于关系不好的牛来说:
a[j]−a[i]>=k即a[i]−a[j]<=−k
然后建图跑最短路就可以了。
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
using namespace std;
#define inf 99999999
const int maxn = 1005;
int map[maxn][maxn],dis[maxn],vis[maxn],cnt[maxn];
int n,ml,md;
void init()
{
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
if(i==j)
map[i][j]=0;
else map[i][j]=map[j][i]=inf;
}
}
}
int spfa(int start)
{
queue<int> q;
int i,now;
memset(vis,0,sizeof vis);
memset(cnt,0,sizeof cnt);
for(int i=1;i<=n;i++)
{
dis[i]=inf;
}
dis[start]=0;
q.push(start);
vis[start]=1;
cnt[start]++;
while(!q.empty())
{
now=q.front();
q.pop();
vis[now]=0;
for(int i=1;i<=n;i++)
{
if(dis[i]>dis[now]+map[now][i])
{
dis[i]=dis[now]+map[now][i];
if(vis[i]==0)
{
q.push(i);
vis[i]=1;
cnt[i]++;
}
if(cnt[i] > n)
{
return -1;
}
}
}
}
if(dis[n] == inf)
{
return -2;
}
return dis[n];
}
int main()
{
int a,b,c,x,y;
while (~scanf("%d %d %d",&n,&ml,&md))
{
init();
for (int i = 1; i < n; i++)
{
map[i + 1][i] = 0;
}
for (int i = 0; i < ml; i++)
{
scanf("%d %d %d",&a,&b,&c);
x = min(a,b);
y = max(a,b);
map[x][y] = c;
}
for (int i = 0; i < md; i++)
{
scanf("%d %d %d",&a,&b,&c);
x = max(a,b);
y = min(a,b);
map[x][y] = -c;
}
int ans = spfa(1);
printf("%d\n",ans);
}
}