POJ - 3169 差分约束
题意:n头牛,按照编号从左到右排列,两头牛可能在一起,接着有一些关系表示第a头牛与第b头牛相隔最多与最少的距离,最后求出第一头牛与最后一头牛的最大距离是多少,如 果最大距离无限大则输出-2,如果关系不能保证则输出-1
题解:差分约束的入门题
差分约束就是如果dis[b]-dis[a]<=c转化为a到b建一条有向边权值为c,接着求最短路就得出了两点的最大距离(最短距离都保证了,那么长一些的也可以成立),注意没有 最短路就是可能性无限,有一个负权回路就是关系不能保证,但是这个题要注意隐含条件就是需要建立每头牛一定不在前一头牛的前面这些边
#include<cstdio> #include<cstring> const int inf=0x3f3f3f3f; const int maxn=50010; struct Edge { int u,v,val; Edge(int u,int v,int val):u(u),v(v),val(val) {} Edge() {} }; struct Edge bellEdge[maxn]; int dis[maxn]; void bellman(int s,int n,int m) { for(int i=0; i<=n; ++i) { dis[i]=inf; } dis[s]=0; int flag; for(int i=0; i<n; ++i) { flag=1; for(int j=0; j<m; ++j) { if(dis[bellEdge[j].u]<inf&&dis[bellEdge[j].v]>dis[bellEdge[j].u]+bellEdge[j].val) { dis[bellEdge[j].v]=dis[bellEdge[j].u]+bellEdge[j].val; flag=0; } } if(flag)//无法再次松弛 return; } if(!flag&&dis[n]<inf)//最后依然可以松弛就是存在负权回路 dis[n]=-1; } int main() { int n,ml,md,m; while(~scanf("%d %d %d",&n,&ml,&md)) { m=0; int u,v,c; for(int i=0; i<ml; ++i) //使用差分约束建立边 { scanf("%d %d %d",&u,&v,&c); bellEdge[m++]=Edge(u,v,c); } for(int i=0; i<md; ++i) { scanf("%d %d %d",&u,&v,&c);//dis[u]-dis[v]<=-c转换为v到u的一条边权值为-c bellEdge[m++]=Edge(v,u,-c); } for(int i=1; i<n; ++i) { bellEdge[m++]=Edge(i+1,i,0); } bellman(1,n,m); if(dis[n]==inf) //无限解 { printf("-2\n"); } else if(dis[n]==-1) //负权回路无解 { printf("-1\n"); } else { printf("%d\n",dis[n]); } } return 0; }