POJ 3169 Layout 【差分约束】+【spfa】

<题目链接>

题目大意:

一些母牛按序号排成一条直线。有两种要求,A和B距离不得超过X,还有一种是C和D距离不得少于Y,问可能的最大距离。如果没有最大距离输出-1,如果1、n之间距离任意就输出-2,否则输出最大的距离。

解题分析:
典型的差分约束,第一种约束,v-u<=c;第二种约束:v-u>=c  可以转化为 u-v<=c ,还有一种约束,因为题目要求按序号排序,所以 loc[i] - loc[i-1]>=0 ,即 loc[i-1]-loc[i]<=0 。以上就是本题的三种约束,利用上述三种约束建图,然后跑一遍最短路即可,因为可能存在负权边,所以用spfa求解。当该图存在负环的时候输出-1,当1~n不连通的时候输出-2,否则输出1---->n的最短边权约束和。即所求的最大距离。

 

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <queue>
 4 #include <algorithm>
 5 using namespace std;
 6 
 7 const int N =1e3+10;
 8 const int M =2e5+10;
 9 #define INF 0x3f3f3f3f
10 struct EDGE{
11     int to,val,next;
12 }edge[M];
13 int head[N],dis[N],cnt[N],tot,n,ml,md;
14 bool vis[N];
15 
16 void init(){
17     memset(head,-1,sizeof(head));
18     tot=0;
19 }
20 void add(int u,int v,int w){
21     edge[++tot].to=v,edge[tot].val=w;
22     edge[tot].next=head[u],head[u]=tot;
23 }
24 int spfa(int s){   //因为存在负权边,所以用spfa求最短路
25     memset(dis,INF,sizeof(dis));
26     memset(vis,false,sizeof(vis));
27     memset(cnt,0,sizeof(cnt));
28     queue<int>q;
29     q.push(s);
30     vis[s]=true,cnt[s]=1,dis[s]=0;
31     while(!q.empty()){
32         int cur=q.front();
33         q.pop();
34         vis[cur]=false;
35         for(int i=head[cur];~i;i=edge[i].next){
36             int v=edge[i].to;
37             if(dis[v]>dis[cur]+edge[i].val){
38                 dis[v]=dis[cur]+edge[i].val;
39                 if(!vis[v]){
40                     vis[v]=true;
41                     if(++cnt[v]>n)return -1;   //进队列次数>n,说明存在负环,直接返回-1
42                     q.push(v);
43                 }
44             }
45         }
46     }
47     if(dis[n]==INF)return -2;    //如果两点不连通,说明1、n两点之间没有约束条件,所以1、n可以距离任意远,返回-2
48     return dis[n];
49 }
50 int main(){
51     while(scanf("%d%d%d",&n,&ml,&md)!=EOF){
52         init();
53         for(int i=1;i<=n;i++)add(i,i-1,0);  //代表s[i-1]-s[i]<=0
54         for(int i=1;i<=ml;i++){
55             int u,v,c;scanf("%d%d%d",&u,&v,&c);
56             add(u,v,c);     //v-u<=c
57         }
58         for(int i=1;i<=md;i++){
59             int u,v,c;scanf("%d%d%d",&u,&v,&c);
60             add(v,u,-c);   //u-v<=-c,即v-u>=c
61         }
62         //利用题目条件,整合成三个差分约束条件,利用这几个条件建图,然后跑一遍最短路
63         printf("%d\n",spfa(1));
64     }
65 }

 

2018-10-11

posted @ 2018-10-11 16:38  悠悠呦~  阅读(236)  评论(0编辑  收藏  举报
浏览器标题切换
浏览器标题切换end