zoukankan      html  css  js  c++  java
  • 洛谷P2136 拉近距离

    题目背景

    我是源点,你是终点。我们之间有负权环。 ——小明

    题目描述

    在小明和小红的生活中,有(N)个关键的节点。有(M)个事件,记为一个三元组((S_i,T_i,W_i)),表示从节点(S_i)有一个事件可以转移到(T_i),事件的效果就是使他们之间的距离减少(W_i)

    这些节点构成了一个网络,其中节点(1)(N)是特殊的,节点(1)代表小明,节点(N)代表小红,其他代表进展的阶段。所有事件可以自由选择是否进行,但每次只能进行当前节点邻接的。请你帮他们写一个程序,计算出他们之间可能的最短距离。

    输入输出格式

    输入格式:

    (1)行,两个正整数(N,M).

    之后(M)行,每行(3)个空格隔开的整数(S_i,T_i,W_i)

    输出格式:

    一行,一个整数表示他们之间可能的最短距离。如果这个距离可以无限缩小,输出(“Forever love”)(不含引号)。

    输入输出样例

    输入样例#1:

    3 3
    1 2 3
    2 3 -1
    3 1 -10
    

    输出样例#1:

    -2
    

    说明

    对于(20\%)数据,(N leq 10,M leq 50)

    对于(50\%)数据,(N leq 300,M leq 5000)

    对于全部数据,(N leq 1000,M leq 10000,|W_i| leq 100),保证从节点(1)(N)有路径。

    思路:题意就是让你在一张图上找一条从(1)号点到(n)号点的最短路径,如果这条路径可以无限缩小,那么就输出(“Forever love”),即存在负环,所以我们可以用(spfa)判断负环,如果一个点入队列超过(n)次,那么一定存在负环,这时直接输出(“Forever love”)并退出程序,然后spfa的过程中更新(dis)数组,即(1)号点到其它点的最短距离,然后这道题还有一个坑点就是距离不一定只有(1)号点能拉近,(n)号点也能,所以我们要用两遍(spfa),分别以(1)号点和(n)号点为起点,然后取两次(dis[end])的最大值,其中(end)表示两次(spfa)的重点。

    代码:

    #include<cstdio>
    #include<cctype>
    #include<queue>
    #include<cstring>
    #include<algorithm>
    #define maxn 1007
    using namespace std;
    int n,m,head[maxn],in[maxn],dis[maxn],num;
    bool vis[maxn];
    inline int qread() {
      char c=getchar();int num=0,f=1;
      for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
      for(;isdigit(c);c=getchar()) num=num*10+c-'0';
      return num*f;
    }
    struct node {
      int v,w,nxt;
    }e[20007];
    inline void ct(int u, int v, int w) {
      e[++num].v=v;
      e[num].w=w;
      e[num].nxt=head[u];
      head[u]=num;
    }
    inline void spfa(int s) {
      memset(dis,0x3f,sizeof(dis));
      queue<int>q;
      q.push(s);
      dis[s]=0,in[s]=1,vis[s]=1;
      while(!q.empty()) {
        int u=q.front();q.pop();
        vis[u]=0;
        for(int i=head[u];i;i=e[i].nxt) {
          int v=e[i].v;
          if(dis[v]>dis[u]+e[i].w) {
            dis[v]=dis[u]+e[i].w;
            if(!vis[v]) {
              q.push(v),vis[v]=1;
              in[v]++;
              if(in[v]>n) {printf("Forever love
    ");exit(0);} 
            }
          }
        }
      }
    }
    int main() {
      n=qread(),m=qread();
      for(int i=1,u,v,w;i<=m;++i) {
        u=qread(),v=qread(),w=qread();
        ct(u,v,-w);
      }
      spfa(1);int zrj=dis[n];
      spfa(n);int cyh=dis[1];
      printf("%d
    ",min(zrj,cyh));
      return 0; 
    }
    
  • 相关阅读:
    vim复制
    嵌入式Linux学习(二)
    (Java实现) 洛谷 P1042 乒乓球
    (Java实现) 洛谷 P1042 乒乓球
    (Java实现) 洛谷 P1071 潜伏者
    (Java实现) 洛谷 P1071 潜伏者
    (Java实现) 洛谷 P1025 数的划分
    (Java实现)洛谷 P1093 奖学金
    (Java实现)洛谷 P1093 奖学金
    Java实现 洛谷 P1064 金明的预算方案
  • 原文地址:https://www.cnblogs.com/grcyh/p/10150949.html
Copyright © 2011-2022 走看看