zoukankan      html  css  js  c++  java
  • P4878 [USACO05DEC]Layout G 差分约束

    题目大意

    • 和人类一样,奶牛们在打饭的时候喜欢和朋友站得很近。
    • 约翰的编号为 1 到 n 的 n(2<=n<=1000) 只奶牛正打算排队打饭。现在请你来安排她们,让她们在数轴上排好队。奶牛的弹性很好,同一个坐标可以站无限只奶牛,排队的顺序必须和她们编号的顺序一致。
    • 有 M 对奶牛互相爱慕,她们之间的距离不能超过一定的值,有 K 对奶牛互相敌视,她们的距离不能小于一定的值。那么,首尾奶牛的最大距离是多少呢?

    输入格式

    • 第一行输入 n,M,K,(0<M,K<=5000)。
    • 接下来 M 行每行三个整数x,y,z,表示编号为 x 和 y 的两头奶牛之间的距离最大不超过 z。
    • 再接下来 K 行每行三个整数 a,b,c,表示编号为 a 和 b 的两头奶牛之间的距离最少为c。

    输出格式

    • 如果没有合理方案,输出 −1,如果首尾两头牛的距离可以无限大,输出 −2,否则输出一个整数表示首尾奶牛的最大距离。

    样例输入

    4 2 1
    1 3 10
    2 4 20
    2 3 3
    

    样例输出

    27
    

    算法分析

    • 不会吧不会吧不会真的有人看不出来这是差分约束吧
    • 然后就是一个差分约束的板子题了
    • 建边跑最短路(求最大值)
    • 建超级源点

    算法展示

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn = 1e3+10,maxm = 2e4+10;
    const int Inf = 0x3f3f3f3f;
    int n;
    int head[maxn],cnt;
    int num[maxn],dis[maxn],vis[maxn];
    
    struct node{
    	int next,to,dis;
    }a[maxm];
    
    void add(int x,int y,int z){
    	a[++cnt].to = y;
    	a[cnt].next = head[x];
    	a[cnt].dis = z;
    	head[x] = cnt;
    }
    
    queue<int> q;
    
    int spfa(int u){
    	memset(dis,0x3f,sizeof(dis));
    	memset(vis,0,sizeof(vis));
    	memset(num,0,sizeof(num));
    	q.push(u);vis[u] = 1;
    	dis[u] = 0;
    	while(!q.empty()){
    		int u = q.front();q.pop();vis[u] = 0;
    		for(int i = head[u];i;i = a[i].next){
    			int v = a[i].to;
    			if(dis[v] > dis[u] + a[i].dis){
    				dis[v] = dis[u] + a[i].dis;
    				if(!vis[v]){
    					vis[v] = 1;q.push(v);
    					num[v]++;
    					if(num[v] > n)return -1;//判负环
    				}
    			}
    		}
    	}
    	if(dis[n] == Inf)return -2;//如果无限大
    	return dis[n];
    }
    
    int main(){
    	int m,k;scanf("%d%d%d",&n,&m,&k);
    	for(int i = 1;i <= m;++i){
    		int x,y,z;scanf("%d%d%d",&x,&y,&z);
    		if(x > y)swap(x,y);
    		add(x,y,z);
    	}
    	for(int i = 1;i <= k;++i){
    		int x,y,z;scanf("%d%d%d",&x,&y,&z);
    		if(x > y)swap(x,y);
    		add(y,x,-z);//建边
    	}
    	for(int i = 1;i < n;++i)add(i+1,i,0);//建边 
    	for(int i = 1;i <= n;++i)add(0,i,0);//超级源点
    	if(spfa(0) == -1){printf("-1
    ");return 0;}//超级源点为起点跑spfa 防止有的负环无法到达的情况
    	printf("%d
    ",spfa(1));
    	return 0;
    }
    

    谢谢观看>:<

  • 相关阅读:
    1.2 偏差与方差
    深度学习中Xavier初始化
    1.1 训练/开发/测试集
    Python笔记(5)类__方法与继承
    Python笔记(4)类__属性与描述符
    Python笔记(3)迭代器与生成器
    Python笔记(2)函数
    线性回归 Linear Regression
    Python笔记(1)变量与表达式
    跳转到某个Activity
  • 原文地址:https://www.cnblogs.com/2004-08-20/p/13324828.html
Copyright © 2011-2022 走看看