Bzoj 1731 POJ 3169 Luogu P4878 Layout
Description:
有n头牛排在一排, 有ML个条件(x,y,w)表示x,y希望彼此之间的距离小于等于w,有MD个条件(x,y,w)表示x,y希望彼此之间的距离大于等于w.
问1号奶牛和N 号奶牛之间的距离最大为多少。无解输出-1,如果有合法方案,但n号点可以在无穷大输出-2.
Analysis:
第一个条件d[x]+w <= d[y],与最短路中的dis[y] >= dis[x] + w,可以把每头牛看做一个点,从x向y连一条边权为w的边;
同理,对于第二个条件,从y向x连一条边权为w的边,这样就可以直接跑最短路,如果出现了负环,那么就无解.
注意:图有可能不连通,因此要从超级源点0向其余点建一条权值为0的边,先从开始跑SPFA。
Code
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
#define N 1100
#define INF 0x3f3f3f3f
using namespace std;
struct edge
{
int to,next,w;
} e[20021];
int head[N],vis[N],dis[N],cnt[N],num_edge,n,ml,md;
void SPFA(int s)
{
queue<int> Q;
memset(dis,0x3f,sizeof(dis));
memset(vis,0,sizeof(vis));
memset(cnt,0,sizeof(cnt));
dis[s] = 0;
Q.push(s);
vis[s] = 1;
while(!Q.empty())
{
int u = Q.front();
Q.pop();
vis[u] = 0;
for(int i = head[u]; i; i = e[i].next)
{
int v = e[i].to;
if(dis[v] > dis[u] + e[i].w)
{
dis[v] = dis[u] + e[i].w;
if(!vis[v])
{
Q.push(v);
vis[v] = 1;
cnt[v]++;
}
if(cnt[v] > n)
{
printf("-1\n");
exit(0);
}
}
}
}
}
void add(int u,int v,int w)
{
e[++num_edge].next = head[u];
e[num_edge].to = v;
e[num_edge].w = w;
head[u] = num_edge;
}
int main()
{
scanf("%d%d%d",&n,&ml,&md);
for(int i = 1;i <= n;++i) add(0,i,0);
for(int i = 1;i <= ml;++i)
{
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
add(a,b,c);
}
for(int i = 1;i <= md;++i)
{
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
add(b,a,-c);
}
SPFA(0);// judge whether the graph is connected
SPFA(1);
if(dis[n] == INF) printf("-2\n");
else printf("%d\n",dis[n]);
return 0;
}
岂能尽如人意,但求无愧我心