当前位置: 代码迷 >> 综合 >> 计算客 - 热爱工作的蒜蒜 - spfa
  详细解决方案

计算客 - 热爱工作的蒜蒜 - spfa

热度:0   发布时间:2024-01-11 16:09:46.0


只有100个点,最短路预处理所有 i 到 j 的最短路,松弛操作时同时更新在最短路条件下该段路经过的避雨路段数(即路长) 。

然后暴力所有区间,O(n2)判断是否起点+该区间+到终点的路长小于 要求


            p = dis[1][i] + dis[i][j] + dis[j][n] ;
            q = num[1][i] + num[i][j] + num[j][n] ;

如满足, 再判断是否淋雨的长度更短,更新即可。


#include <bits/stdc++.h>
#include <climits>
using namespace std;
typedef long long ll ;int n , m1 , m2 , len ;const int inf = 0x3f3f3f3f ;
const int maxn = 150 ;
struct edge{int u , v ;ll w ;bool real ;
};
vector<int> g[maxn] ;
vector<edge> Edge ;
int inq[maxn] ;ll dis[maxn][maxn] ;
ll num[maxn][maxn] ;
void addEdge(int u , int v , ll w , bool r){edge temp ;temp.u = u , temp.v = v , temp.w = w ;temp.real = r ;Edge.push_back(temp) ;g[u].push_back(Edge.size() - 1 ) ;
}
bool spfa(int u)
{int i , k ;//for(int i = 0 ; i <= n ; i ++ )dis[u][i] = inf ;memset(inq , 0 , sizeof(inq)) ;dis[u][u] = 0 , inq[u] = 1 ;queue<int> q ;q.push(u) ;while(! q.empty()) {int t = q.front() ; q.pop() ;inq[t] = 0 ;for(k = 0 ; k < g[t].size() ; k ++ ){edge e = Edge[ g[t][k] ] ;if(dis[u][e.v] > dis[u][e.u] + e.w){dis[u][e.v]= dis[u][e.u] + e.w ;if(e.real == true) num[u][e.v] = num[u][e.u] + 1 ;else  num[u][e.v] = num[u][e.u] ;//pre[e.v] = e.u ;if(! inq[e.v]){inq[e.v] = 1 ;q.push(e.v) ;}}}}return true ;
}
void work(ll & len_temp , ll & num_temp){for(int i = 0 ; i <= n ; i ++ ) dis[i][i] = 0 ;for(int i = 1 ; i <= n ; i ++ ) spfa(i) ;int temp = dis[1][n] ;if(temp > len) {num_temp = -1 ;return  ;}len_temp = temp ;num_temp = num[1][n] ;int p , q ;for(int i = 1 ; i <= n ; i ++ ){for(int j = i + 1 ; j <= n ; j ++ ){p = dis[1][i] + dis[i][j] + dis[j][n] ;q = num[1][i] + num[i][j] + num[j][n] ;if(p <= len){if(p - q < len_temp - num_temp){num_temp = q ;len_temp = p ;}}}}//return num_temp ;
}
int main(){int T ; scanf("%d" , &T) ;int u , v ; ll  w;while( T -- ){scanf("%d %d %d %d" , &n , &m1 , &m2 , &len) ;for(int i = 0 ; i <= n ; i ++ ) g[i].clear() ;Edge.clear() ;memset(dis , inf , sizeof(dis)) ;memset(num , 0 , sizeof(num)) ;for(int i = 0 ; i < m1 ; i ++ ){scanf("%d %d" , &u , &v) ;addEdge(u , v , 1 , 1 ) ;addEdge(v , u , 1 , 1 ) ;}for(int i = 0 ; i < m2 ; i ++ ){scanf("%d %d %lld" , &u , &v , &w) ;addEdge(u , v , w , 0 ) ;addEdge(v , u , w , 0 ) ;}ll num_temp = 0 , len_temp = 0 ;work(len_temp , num_temp) ;printf("%lld\n" , num_temp == -1 ? -1 : len_temp - num_temp ) ;}return 0 ;
}