• luogu 1993 小k的农场


    题目描述

    小K在MC里面建立很多很多的农场,总共n个,以至于他自己都忘记了每个农场中种植作物的具体数量了,他只记得一些含糊的信息(共m个),以下列三种形式描述:

    • 农场a比农场b至少多种植了c个单位的作物,
    • 农场a比农场b至多多种植了c个单位的作物,
    • 农场a与农场b种植的作物数一样多。

    但是,由于小K的记忆有些偏差,所以他想要知道存不存在一种情况,使得农场的种植作物数量与他记忆中的所有信息吻合。

    输入格式

    第一行包括两个整数 n 和 m,分别表示农场数目和小 K 记忆中的信息数目。

    接下来 m 行:

    如果每行的第一个数是 1,接下来有 3 个整数 a,b,c,表示农场 a 比农场 b 至少多种植了 c 个单位的作物。

    如果每行的第一个数是 2,接下来有 3 个整数 a,b,c,表示农场 a 比农场 b 至多多种植了 c 个单位的作物。如果每行的第一个数是 3,接下来有 2 个整数 a,b,表示农场 a 种植的的数量和 b 一样多。

    输出格式

    如果存在某种情况与小 K 的记忆吻合,输出“Yes”,否则输出“No”。

    输入输出样例

    输入 #1
    3 3
    3 1 2
    1 1 3 1
    2 2 3 2
    
    输出 #1
    Yes
    

    说明/提示

    对于 100% 的数据保证:1 ≤ n,m,a,b,c ≤ 10000。

    分析

    差分约束,和糖果很像有木有

    至多那个加成负权就好,0那个要连双向

    跑一个最长路,看有没有环

    这题竟然卡SPFA,加优化就好

    代码

      1 /**************************
      2 User:Mandy.H.Y
      3 Language:c++
      4 Problem:luogu1993
      5 Algorithm:
      6 **************************/
      7 #include<bits/stdc++.h>
      8 
      9 using namespace std;
     10 
     11 const int maxn = 1e4 + 5;
     12 
     13 int n,m,size;
     14 int dis[maxn],cnt[maxn];
     15 bool vis[maxn];
     16 int first[maxn];
     17 int q[100005],l,r;
     18 
     19 struct Edge{
     20     int v,w,nt;
     21 }edge[maxn << 1];
     22 
     23 template<class T>inline void read(T &x){
     24     x = 0;bool flag = 0;char ch = getchar();
     25     while(!isdigit(ch)) flag |= ch == '-',ch = getchar();
     26     while(isdigit(ch)) x = (x << 1) + (x << 3) + (ch ^ 48),ch = getchar();
     27     if(flag) x = -x;
     28 }
     29 
     30 void file(){
     31     freopen("testdata.in","r",stdin); 
     32 //    freopen("1993.out","w",stdout); 
     33 }
     34 
     35 void eadd(int u,int v,int w){
     36     edge[++size].v = v;
     37     edge[size].w = w;
     38     edge[size].nt = first[u];
     39     first[u] = size;
     40 }
     41 
     42 void readdata(){
     43     read(n);read(m);
     44     for(int i = 1;i <= m; ++ i){
     45         int opt,a,b,c;
     46         read(opt);
     47         switch(opt){
     48             case 1:{
     49                 read(a);read(b);read(c);
     50                 eadd(b,a,c);
     51                 break;
     52             }
     53             case 2:{
     54                 read(a);read(b);read(c);
     55                 eadd(a,b,-c);
     56                 break;
     57             }
     58             default:{
     59                 read(a);read(b);
     60                 eadd(a,b,0);
     61                 eadd(b,a,0);
     62                 break;
     63             }
     64         }
     65         if(opt == 1 && a == b && c != 0) {
     66             puts("No");
     67             exit(0);
     68         }
     69     }
     70 }
     71 
     72 void work(){
     73 //    queue<int>q;
     74     for(int i = 1;i <= n ; ++ i){
     75         q[r++] = i;
     76         vis[i] = 1;
     77     }
     78     while(l != r){
     79         int u = q[l];
     80         l++;
     81         l %= 100000;
     82         vis[u] = 0;
     83         int rr = (r-1 + 100000) % 100000;
     84         if(l != r) if(dis[q[l]] < dis[q[rr]]) swap(q[l],q[rr]);
     85         if(cnt[u] > n) {
     86             puts("No");
     87             return;
     88         } 
     89         for(int i = first[u];i;i = edge[i].nt){
     90             int v = edge[i].v;
     91             int w = edge[i].w;
     92             
     93             if(dis[v] < dis[u] + w){
     94                 dis[v] = dis[u] + w;
     95                 cnt[v] = cnt[u] + 1;
     96                 if(!vis[v]) {
     97                     q[r++] = v;
     98                     r %= 100000;
     99                     int rr = (r-1 + 100000) % 100000;
    100                     if(l != r) if(dis[q[l]] < dis[q[rr]]) swap(q[l],q[rr]);
    101                     vis[v] = 1;
    102                 }
    103             }
    104         }
    105     }
    106     puts("Yes");
    107 }
    108 
    109 int main(){
    110 //    file();
    111     readdata();
    112     work();
    113     return 0;
    114 }
    View Code
  • 相关阅读:
    微软面试题: LeetCode 907. 子数组的最小值之和 middle 出现次数:1
    微软面试题: LeetCode 5. 最长回文子串 出现次数:1
    微软面试题: LeetCode 120. 三角形最小路径和 出现次数:1
    开源项目推荐:主流RPC开源框架及知识科普
    微软面试题: LeetCode 84. 柱状图中最大的矩形 出现次数:1
    需重点掌握的三大排序: 快速排序 + 归并排序 + 堆排序
    微软面试题:补充题12. 二叉树的下一个节点 出现次数:2
    微软面试题: 剑指 Offer 51. 数组中的逆序对 出现次数:2
    GUI
    数据结构与算法
  • 原文地址:https://www.cnblogs.com/Mandy-H-Y/p/11465853.html
Copyright © 2020-2023  润新知