• luogu 2294 [HNOI2005]狡猾的商人


    Description

    刁姹接到一个任务,为税务部门调查一位商人的账本,看看账本是不是伪造的。账本上记录了n个月以来的收入情况,其中第i 个月的收入额为Ai(i=1,2,3...n-1,n), 。当 Ai大于0时表示这个月盈利Ai 元,当 Ai小于0时表示这个月亏损Ai 元。所谓一段时间内的总收入,就是这段时间内每个月的收入额的总和。 刁姹的任务是秘密进行的,为了调查商人的账本,她只好跑到商人那里打工。她趁商人不在时去偷看账本,可是她无法将账本偷出来,每次偷看账本时她都只能看某段时间内账本上记录的收入情况,并且她只能记住这段时间内的总收入。 现在,刁姹总共偷看了m次账本,当然也就记住了m段时间内的总收入,你的任务是根据记住的这些信息来判断账本是不是假的。

    Input

    第一行为一个正整数w,其中w < 100,表示有w组数据,即w个账本,需要你判断。每组数据的第一行为两个正整数n和m,其中n < 100,m < 1000,分别表示对应的账本记录了多少个月的收入情况以及偷看了多少次账本。接下来的m行表示刁姹偷看m次账本后记住的m条信息,每条信息占一行,有三个整数s,t和v,表示从第s个月到第t个月(包含第t个月)的总收入为v,这里假设s总是小于等于t。

    Output

    包含w行,每行是true或false,其中第i行为true当且仅当第i组数据,即第i个账本不是假的;第i行为false当且仅当第i组数据,即第i个账本是假的。

    Sample Input


    3 3 
    1 2 10
    1 3 -5
    3 3 -15
    5 3
    1 5 100
    3 5 50
    1 2 51

    Sample Output

    true 
    false
     

    分析

    解法一 差分约束

    s月到t月共收入v元,从s-1到t连一条长度为v的边

    图没有环

    对于每一个入度为零的点,跑两遍SPFA(最长/最短)

    比较各个点的(能到达的点)两个距离是否一样,不一样就false,

    一样就继续找入度为零的点

    注意每一次SPFA前要初始化

    因为这个距离是相对起点而言,所以各个起点是独立的

    不能只在最后判断最长最短是否一样

      1 /*********************
      2 User:Mandy.H.Y
      3 Language:c++
      4 Problem:luogu2294
      5 Algorithm:
      6 *********************/
      7 #include<bits/stdc++.h>
      8 
      9 using namespace std;
     10 
     11 const int maxn = 105;
     12 const int maxm = 1005;
     13 const int mod = 1e5;
     14 
     15 int W,n,m,size;
     16 int first[maxn];
     17 int dis1[maxn],dis2[maxn],ind[maxn];
     18 int q[100005],l,r;
     19 bool vis[maxn];
     20 
     21 struct Edge{
     22     int v,nt,w;
     23 }edge[maxm];
     24 
     25 template<class T>inline void read(T &x){
     26     x = 0;bool flag = 0;char ch = getchar();
     27     while(!isdigit(ch)) flag |= ch == '-',ch = getchar();
     28     while(isdigit(ch)) x = (x << 1) + (x << 3) + (ch ^ 48),ch = getchar();
     29     if(flag) x = -x;
     30 }
     31 
     32 void file(){
     33     freopen("2294.in","r",stdin);
     34     freopen("2294.out","w",stdout);
     35 }
     36 
     37 void init(){
     38     size = 0;
     39     memset(first,0,sizeof(first));
     40     memset(edge,0,sizeof(edge));
     41     memset(ind,0,sizeof(ind));
     42 }
     43 
     44 void eadd(int u,int v,int w){
     45     edge[++size].v = v;
     46     edge[size].w = w;
     47     edge[size].nt = first[u];
     48     first[u] = size;
     49 }
     50 
     51 void readdata(){
     52     read(n);read(m);
     53     for(int i = 1;i <= m; ++ i){
     54         int u,v,w;
     55         read(u);read(v);read(w);
     56         eadd(u-1,v,w);
     57         ind[v] ++;
     58     }
     59 }
     60 
     61 bool SPFA(int x){
     62     l = r = 0;
     63     q[r++] = x;
     64     memset(vis,0,sizeof(vis));
     65     while(l != r){
     66         int u = q[l];
     67         l ++ ; l %= mod;
     68         int rr = (r - 1 + mod) % mod;
     69         if(l != r) if(dis1[q[l]] > dis1[q[rr]]) swap(q[l],q[rr]);
     70         vis[u] = 0;
     71         for(int i = first[u];i;i = edge[i].nt){
     72             int v = edge[i].v;
     73             int w = edge[i].w;
     74             if(dis1[v] > dis1[u] + w){
     75                 dis1[v] = dis1[u] + w;
     76                 if(!vis[v]){
     77                     q[r++] = v;
     78                     vis[v] = 1;
     79                     r %= mod;
     80                     int rr = (r - 1 + mod) % mod;
     81                     if(l != r) if(dis1[q[l]] > dis1[q[rr]]) swap(q[l],q[rr]);
     82                 } 
     83             }
     84         }
     85     }
     86     
     87         
     88     l = r = 0;
     89     q[r++] = x;
     90     memset(vis,0,sizeof(vis));
     91     while(l != r){
     92         int u = q[l];
     93         l ++ ; l %= mod;
     94         int rr = (r - 1 + mod) % mod;
     95         if(l != r) if(dis2[q[l]] < dis2[q[rr]]) swap(q[l],q[rr]);
     96         vis[u] = 0;
     97         for(int i = first[u];i;i = edge[i].nt){
     98             int v = edge[i].v;
     99             int w = edge[i].w;
    100             if(dis2[v] < dis2[u] + w){
    101                 dis2[v] = dis2[u] + w;
    102                 if(!vis[v]){
    103                     q[r++] = v;
    104                     vis[v] = 1;
    105                     r %= mod;
    106                     int rr = (r - 1 + mod) % mod;
    107                     if(l != r) if(dis2[q[l]] < dis2[q[rr]]) swap(q[l],q[rr]);
    108                 }
    109             }
    110         }
    111     }
    112     
    113     for(int i = 1;i <= n; ++ i){
    114         if(dis1[i] != 0x3f3f3f3f && dis1[i] != dis2[i]){
    115             return 0;
    116         }
    117     }
    118     return 1;
    119     
    120 }
    121 
    122 void work(){
    123     init();
    124     readdata();
    125     
    126     for(int i = 0;i <= n; ++ i){
    127         if(ind[i] == 0){
    128             
    129             memset(dis1,0x3f3f3f3f,sizeof(dis1));
    130             memset(dis2,128,sizeof(dis2));
    131 
    132             dis1[i] = 0;
    133             dis2[i] = 0;
    134             if(!SPFA(i)) {
    135                 puts("false");
    136                 return;
    137             }
    138         }
    139     }
    140     puts("true");
    141 }
    142 
    143 int main(){
    144 //    file();
    145     read(W);
    146     while(W -- ) work();
    147     return 0;
    148 }
    View Code

    解法二 带权并查集

  • 相关阅读:
    彼之蜜糖,吾之砒霜——聊聊软件开发中的最佳实践
    WebAPI框架里设置异常返回格式统一
    Entity Framework Plus
    实体框架自定义代码优先约定(EF6以后)
    npm 切换淘宝镜像几种方式
    EntityFramework中Json序列化的循环引用问题解决--Newtonsoft.Json
    Json序列化循环引用的问题
    Windows Service 之 安装失败后的删除
    Windows Service 之 详解(二)
    Windows Service 之 详解(一)
  • 原文地址:https://www.cnblogs.com/Mandy-H-Y/p/11468127.html
Copyright © 2020-2023  润新知