【codeforce Gym 100570B】【最短路SPFA】 ShortestPath Query 【询问单源最短路径,每条边有一个颜色,要求路径上相邻边的颜色不能相同】

传送门:gym 100570B

描述:

B. ShortestPath Query
time limit per test
1 second
memory limit per test
256 megabytes
input
standard input
output
standard output

De Prezer loves troyic paths.Consider we have a graph with n vertices and m edges.Edges are directed in one way.And there is at most one edge from any vertex to any other vertex.If there is an edge from v to u, then c(v, u) is its color and w(v, u) is its length.Otherwise,c(v, u) = w(v, u) =  - 1.

A sequence p1, p2, ..., pk is a troyic path is and only if for each 1 ≤ i ≤ k1 ≤ pi ≤ n and if i < k, then c(pi, pi + 1) >  - 1 and if i + 1 < k, then c(pi, pi + 1) ≠ c(pi + 1, pi + 2) .

The length of such troyic path is  and it's called a p1 - pk path.

In such graph, length of the shortest path from vertex v to u is the minimum length of all v - u paths.(The length of the shortest path from any vertex to itself equals 0)

De Prezer gives you a graph like above and a vertex s.

De Prezer also loves query. So he gives you q queries and in each query, gives you number t and you should print the length of the shortest path from s to t (or  - 1 if there is no troyic path from s to t)

Input

The first line of input contains three integers n and m and C, the number of vertices, the numbers of edges and the number of valid colors.

The next m lines, each line contains 4 integers v, u, w(v, u), c(v, u) (1 ≤ v, u ≤ n and v ≠ u and 1 ≤ w(v, u) ≤ 109 and 1 ≤ c(v, u) ≤ C).

The line after that contains integer s and q.

The next q lines, each line contains information of one query, number t.

1 ≤ n, m, C, q ≤ 105

m ≤ n(n - 1)

1 ≤ s, t ≤ n

Output

For each query, print the answer.

Examples
input
5 4 1000
1 2 10 1
2 3 10 2
3 4 10 2
4 5 10 1
1 5
1
2
3
4
5
output
0
10
20
-1
-1
input
5 5 2
1 2 10 1
2 3 10 2
3 4 10 1
4 5 10 2
1 5 39 1
1 5
1
2
3
4
5
output
0
10
20
30
39

题意:

询问单源最短路径,每条边有一个颜色,要求路径上相邻边的颜色不能相同,无重边且边权为正。

思路:

因为路径的合法性和边的颜色有关,

所以在做spfa的时候,把边丢到队列中去,松弛的时候注意判断一下颜色,d数组表示到这条边的出点v的距离。

期望复杂度是O(km),k是边入队次数,m是边数。最后根据边来松弛顶点,O(m),总复杂度是O(km+m)。


一开始想的Dijkstra(看到边权为正。。),存点和之前边的颜色每次更新的时候判断来的那个点的颜色和当前边的颜色是否一样,WA了,很快我就意识到,入点不能只保存最短路径的颜色c1,如果边的颜色和c1一样,那么会判成路径不合法,但是实际上可能还存在一条次短路径且颜色和c1不等,所以不能只存点的颜色,应该按照题意用spfa去跑并且满足相邻边的颜色不同。

代码:

#include <bits/stdc++.h>
using  namespace  std;

#define ll __int64
#define rep(i,k,n) for(int i=k;i<=n;i++)

template<class T> T sqr(T x){ return x * x; }
template<class T> T gcd(T a, T b){ return b ? gcd(b, a%b) : a; }
template<class T> void read(T&num) {
    char CH; bool F=false;
    for(CH=getchar();CH<'0'||CH>'9';F= CH=='-',CH=getchar());
    for(num=0;CH>='0'&&CH<='9';num=num*10+CH-'0',CH=getchar());
    F && (num=-num);
}

const ll inf = 0x3f3f3f3f3f3f3f3fLL;
const int N=1e5+10;

int  head[N], to[N], nxt[N], col[N], wei[N], vis[N], etol;
ll d[N];//edge
ll dd[N];//vertex
int n, m, s, t, C, q;

void spfa(){
  memset(d, 0x3f, sizeof(ll) * m);
  memset(vis, 0, sizeof(vis));
  queue<int>q;
  for(int i = head[s]; ~i; i = nxt[i]){//把s作为入点的边先加入队列
    q.push(i); vis[i] = 1; d[i] = wei[i];
  }

  while(!q.empty()){
    int e = q.front(); q.pop(); vis[e] = 0;
    for(int i = head[to[e]]; ~i; i = nxt[i]){
      if(col[i] != col[e] && wei[i] + d[e] < d[i]){
        d[i] = wei[i] + d[e];
        if(!vis[i]){ q.push(i); vis[i] = 1;}
      }
    }
  }  

  memset(dd+1, 0x3f, sizeof(ll) * n);
  dd[s]=0;
  rep(i, 0, m-1){
    dd[to[i]] = min(dd[to[i]], d[i]);
  }
}


inline void addedge(int u, int v, int w, int c){
  to[etol] = v;
  wei[etol] = w;
  col[etol] = c;
  nxt[etol] = head[u];
  head[u] = etol++;
}

int  main(){
  read(n),read(m),read(C);
  memset(head+1, -1, sizeof(int) * n);
  rep(i, 1, m){
    int u, v, w, c;
    read(u),read(v),read(w),read(c);
    addedge(u, v, w, c);
  }
  read(s),read(q);

  spfa();
  rep(i, 1, q){
    read(t);
    printf("%I64d\n", dd[t] == inf ? -1: dd[t]);
  }
  return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值