zoukankan      html  css  js  c++  java
  • 【GDOI】【图论-最短路】时间与空间之旅

    最近打的一场校内训练的某题原题。。。

    题目如下:

    Description

    公元22××年,宇宙中最普遍的交通工具是spaceship。spaceship的出现使得星系之间的联系变得更为紧密,所以spaceship船长也成了最热门的职业之一。当然,要成为一名出色的船长,必须通过严格的考核,例如下面是最简单的问题中的一个。
    用1~n的整数给n个星系标号,目前你在标号为1的星系,你需要送快递到标号为n的星系,星系之间由于存在陨石带,并不是都可以直连的。同时,由于超时空隧道的存在,在某些星系间飞行会出现时间静止甚至倒流,飞行时间为0或为负数。另外,由星系i到星系j的时间和由星系j到星系i的时间不一定是相同的。
    在寄出日期之前收到快递被认为是不允许的,所以每部spaceship上都有一个速度调节装置,可以调节飞行的时间。简单来说其功能就是让所有两个星系间的飞行时间(如果可以直达)都增加或减少相同的整数值,你的任务就是调整速度调节器,找出一条用最短时间完成任务的路径,并且保证这个最短时间的值大于或等于0。

    INPUT

    输入文件包含多组数据,第1个数为T,表示数据的数量。
    对于每一组数据,输入第1行为两个正整数N(2≤N≤100),E(1≤E≤N*(N-1)/2),为星系的个数和星系间飞行的路线数。然后E行,每行三个整数i,j和t(1≤i,j≤N,i≠j,-100000≤t≤100000),表示由星系i到星系j飞行的时间为t。由i到j最多只会有一条飞行线路。

    OUTPUT

    输出文件共T行,每组数据输出一行;
    如果可以通过调节速度调节器完成任务,则输出一个非负整数,表示由星系1到星系N的最短时间。
    如果不能由星系1到达星系N,则输出-1

    SAMPLEINPUT

    1
    4 5
    1 2 1
    1 3 1
    2 3 -3
    3 1 1
    3 4 1

    SAMPLEOUTPUT

    2

    HINT

    样例说明
    
    输入样例如图所示,其中节点标号表示相应星系,节点间数字表示所需时间。
    
    如果设置速度控制器的值为0,则有如下路径:12312→……→34,使得投递的时间为负无穷大,显然是不符合要求的,所以应该把速度控制器的值设为1,相当于每个时间值加1,得到的最短路径为1→234,所需时间为2+(-2)+2=2

    --------------以下是题解-----------------------------

    题意简析:题目就是给你一张有向图,你可以对图中所有边的边权加上或者减去一个整数,使得从1~n的最短路在非负的前提下最小。

    解题思路:首先用floyd判断是否有解,然后二分答案用SPFAcheck是否有负环并求解,注意解的合法性即可。

    附代码:

      1 #include<cstdio>
      2 #include<iostream>
      3 #include<cstring>
      4 #include<string>
      5 #include<algorithm>
      6 #include<map>
      7 #include<set>
      8 #include<vector>
      9 #include<cmath>
     10 #define For(i,a,b) for (int i=a; i<=b; i++)
     11 #define Ford(i,a,b) for (int i=a; i>=b; i--)
     12 #define File(fn) freopen(fn".in","r",stdin); freopen(fn".out","w",stdout);
     13 #define mem(qaq,num) memset(qaq,num,sizeof(qaq));
     14 #define ll long long
     15 #define mod 1000000007
     16 #define INF 2000000000
     17 using namespace std;
     18 struct edge{
     19     int to,next,v;
     20 }e[100001];
     21 int head[100001];
     22 int rep[100001];
     23 int dist[100001];
     24 bool mrk[100001];
     25 int go[101][101];
     26 int q[2000001];
     27 int T,n,m,l,r,cnt,ans;
     28 inline int in(){
     29     int x=0,f=1;
     30     char ch=getchar();
     31     while (ch<'0'||ch>'9') f=ch=='-'?-1:1,ch=getchar();
     32     while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
     33     return x*f;
     34 }
     35  
     36 inline void ins(int u,int v,int w)
     37 {
     38     e[++cnt].to=v;
     39     e[cnt].v=w;
     40     e[cnt].next=head[u];
     41     head[u]=cnt;
     42 }
     43 inline int check(int lim)  
     44 {  
     45     For(i,1,n)mrk[i]=0;
     46     For(i,1,n)dist[i]=INF;
     47     For(i,1,n)rep[i]=0;
     48     memset(q,0,sizeof(q));
     49     q[1]=1;mrk[1]=1;dist[1]=0;rep[1]=1;
     50     int t=0,w=1;
     51     while (t<w)
     52     {  
     53         int now=q[++t];
     54         mrk[now]=0;
     55         for (int i=head[now];i;i=e[i].next)
     56         {
     57           if (dist[e[i].to]>dist[now]+e[i].v+lim&&go[e[i].to][n])
     58           {
     59             dist[e[i].to]=dist[now]+e[i].v+lim;
     60              
     61             if (!mrk[e[i].to]&&rep[e[i].to]<=n)
     62             {  
     63                 mrk[e[i].to]=1;
     64                 rep[e[i].to]++;
     65                 if (rep[e[i].to]>n)return -1;
     66                 q[++w]=e[i].to;
     67             }  
     68           }
     69       }
     70     }
     71     return dist[n];
     72 }
     73 inline void doit()
     74 {
     75     mem(e,0);
     76     mem(head,0);
     77     mem(go,0);
     78     cnt=0;
     79     n=in(),m=in();
     80     int mn=INF;
     81     int mx=-INF;
     82     For(i,1,m)
     83     {
     84         int x,y,z;
     85         x=in(),y=in(),z=in();
     86         ins(x,y,z);
     87         mn=min(mn,z);
     88         mx=max(mx,z);
     89         go[x][y]=1;
     90     }
     91     For(i,1,n)go[i][i]=1;
     92     For(k,1,n)
     93         For(i,1,n)
     94             For(j,1,n)
     95                 go[i][j]=go[i][j]|(go[i][k]&go[k][j]);
     96     if (!go[1][n]){printf("-1
    ");return;}
     97     l=-mx;r=-mn;
     98     ans=-1;
     99     while (l<=r)
    100     {
    101         int mid=(l+r)>>1,now=check(mid);
    102         if (now>=0&&now!=INF){ans=now;r=mid-1;}
    103         else l=mid+1;
    104     }
    105     printf("%d
    ",ans);
    106 } 
    107 int main()
    108 {
    109     T=in();
    110     while (T--)doit();
    111 }

     本文由Melacau编写,Melacau代表M星向您问好,如果您不是在我的博客http://www.cnblogs.com/Melacau上看到本文,请您向我联系,email:13960948839@163.com.

  • 相关阅读:
    SAP 锁对象
    smartforms取消word为默认编辑器
    abap 配置 zconfig
    Ant步步为营(1)解压本地的zip包
    点击页面出现文字动画
    js简单实现累加
    github发布线上项目
    jsonp的实现
    js操作class
    js开发实用技巧
  • 原文地址:https://www.cnblogs.com/Melacau/p/tstrip.html
Copyright © 2011-2022 走看看