NYOJ 247

View Code
  1 /*

  2 思路:

  3 利用最短路的变形

  4 分别从起点搜一次

  5 从终点搜一次

  6 从起点搜出从起点到达各点的最小值

  7 从终点搜出从终点到达各点的最大值(所有可以到达的点)

  8 

  9 主要思想是:

 10 从  1  到  i  再从 i 到  n

 11 从 1 到 i 时 路径是正着存的

 12 

 13 从i 到  n 时我们把路径反着存一次

 14 变成求  从 n  到 i 了(此处最重要) 

 15 */

 16 #include<iostream>

 17 #include<cstdio>

 18 #include<cstring>

 19 #include<queue>

 20 #define qmax(a,b) ((a)>(b))?(a):(b)

 21 #define qmin(a,b) ((a)<(b))?(a):(b)

 22 using namespace std;

 23 

 24 const int roadnum=500001;

 25 const int citynum=100001;

 26 struct node

 27 {

 28    int e;

 29    int next; 

 30 }edge[roadnum*2];

 31 

 32 int k1[citynum],k2[citynum];

 33 bool flag1[citynum],flag2[citynum];

 34 int maxval[citynum],minval[citynum];

 35 int n,m;

 36 int k=0;

 37 queue <int> q;

 38 

 39 void ADD(int from,int to)

 40 {

 41    edge[k].e=to;

 42    edge[k].next=k1[from];

 43    k1[from]=k++;

 44    

 45    edge[k].e=from;

 46    edge[k].next=k2[to];

 47    k2[to]=k++;

 48 }

 49 

 50 void init()

 51 {

 52    int i,x,y,z;

 53    memset(flag1,0,sizeof(flag1));

 54    memset(flag2,0,sizeof(flag2));

 55    memset(k1,-1,sizeof(k1));//从起点搜索用 

 56    memset(k2,-1,sizeof(k2));//从终点搜索用 

 57    for(i=1;i<=n;++i)

 58     {

 59        scanf("%d",&minval[i]);

 60        maxval[i]=minval[i];

 61     }

 62    while(m--)

 63     {

 64        scanf("%d%d%d",&x,&y,&z);

 65        ADD(x,y);

 66        if(2==z)ADD(y,x); 

 67     }

 68 }

 69 

 70 int spfa()

 71 {

 72   int x,y,i;

 73   while(!q.empty())q.pop();

 74   q.push(1);

 75   flag1[1]=1;

 76   while(!q.empty())// 这个while()  控制从 从起点 可以到达的所有点可以取的最小值 

 77    {

 78      x = q.front();

 79      q.pop();

 80      for(i=k1[x];i!=-1;i=edge[i].next)

 81       {

 82          y= edge[i].e;

 83          minval[y]=qmin(minval[x],minval[y]);

 84          if(!flag1[y])

 85           {

 86             q.push(y);

 87             flag1[y]=1;

 88           }

 89       }

 90    }

 91    

 92    q.push(n);

 93    flag2[n]=1;

 94    while(!q.empty())// 因为路径反着存了一次  我们从终点 逆向搜回去  可以到达各点的最大值 

 95     {              //相当于从各点走到终点的最大值(因为路径反存了一次) 

 96        x = q.front();

 97        q.pop();

 98        for(i=k2[x];i!=-1;i=edge[i].next)

 99         {

100            y = edge[i].e;

101            maxval[y]=qmax(maxval[x],maxval[y]);

102            if(!flag2[y])

103             {

104               q.push(y);

105               flag2[y]=1;

106             }

107         }

108     }

109   int te=0;

110   for(i=1;i<=n;++i)

111    if(flag1[i] && flag2[i] && maxval[i]-minval[i]>te)// flag1[i]!=0表明从起点可以到这个点 

112     te=maxval[i]-minval[i];                   //flag2[i]!=0表明从点 i 可以到达终点 

113   return te;

114 }

115 

116 int main()

117 {

118    while(EOF != scanf("%d%d",&n,&m))

119     {

120        init();

121        printf("%d\n",spfa());

122     }

123    return 0;

124 }

 

你可能感兴趣的:(OJ)