poj3114:题目链接
.题目大意:给出n个城市,m条送信的渠道,u v w代表u城市送信到v城市需要w小时。同时如果两个城市属于一个国家,那么送信时间为0,在一个国家中的条件是所有城市相互之间可以送信到达。
强连通找出连通块,那么每个连通块就是一个国家,缩点,重新建图,spfa找出要求的最短路径
#include <cstdio>
#include <cstring>
#include <stack>
#include <queue>
#include <algorithm>
using namespace std ;
#define INF 0x3f3f3f3f
struct node{
int u , v , w ;
int next ;
}edge[500000] , tree[500000];
int head[510] , h_tree[510] , cnt ;
int low[510] , dnf[510] , time ;
int belong[510] , vis[510] , dis[510] , num ;
queue <int> que ;
stack <int> sta ;
void init() {
cnt = time = num = 0 ;
memset(head,-1,sizeof(head)) ;
memset(h_tree,-1,sizeof(head)) ;
memset(low,0,sizeof(low)) ;
memset(dnf,0,sizeof(dnf)) ;
memset(belong,0,sizeof(belong)) ;
memset(vis,0,sizeof(vis)) ;
}
void add(int u,int v,int w) {
edge[cnt].u = u ; edge[cnt].v = v ; edge[cnt].w = w ;
edge[cnt].next = head[u] ; head[u] = cnt++ ;
}
void add_tree(int u,int v,int w) {
tree[cnt].u = u ; tree[cnt].v = v ; tree[cnt].w = w ;
tree[cnt].next = h_tree[u] ; h_tree[u] = cnt++ ;
}
void tarjan(int u) {
dnf[u] = low[u] = ++time ;
vis[u] = 1 ;
sta.push(u) ;
int i , v ;
for(i = head[u] ; i != -1 ; i = edge[i].next) {
v = edge[i].v ;
if( !dnf[v] ) {
tarjan(v) ;
low[u] = min(low[v],low[u]) ;
}
else if( vis[v] )
low[u] = min(low[u],dnf[v]) ;
}
if( low[u] == dnf[u] ) {
++num ;
while( 1 ) {
i = sta.top() ;
sta.pop() ;
vis[i] = 0 ;
belong[i] = num ;
if( i == u ) break ;
}
}
}
int spfa(int u,int s) {
while( !que.empty() ) que.pop() ;
memset(vis,0,sizeof(vis)) ;
memset(dis,INF,sizeof(dis)) ;
vis[u] = 1 ;
dis[u] = 0 ;
que.push(u) ;
int i , v ;
while( !que.empty() ) {
u = que.front() ;
que.pop() ;
vis[u] = 0 ;
for(i = h_tree[u] ; i != -1 ; i = tree[i].next) {
v = tree[i].v ;
if( dis[v] > dis[u] + tree[i].w ) {
dis[v] = dis[u] + tree[i].w ;
if( !vis[v] ) {
vis[v] = 1 ;
que.push(v) ;
}
}
}
}
return dis[s] ;
}
int main() {
int n , m , q ;
int u , v , w , i , j ;
while( scanf("%d %d", &n, &m) && n+m > 0 ) {
init() ;
while( m-- ) {
scanf("%d %d %d", &u, &v, &w) ;
add(u,v,w) ;
}
for(i = 1 ; i <= n ; i++)
if( !dnf[i] ) tarjan(i) ;
for(i = 1 , cnt = 0 ; i <= n ; i++) {
for(j = head[i] ; j != -1 ; j = edge[j].next) {
u = belong[ edge[j].u ] ;
v = belong[ edge[j].v ] ;
w = edge[j].w ;
if( u != v )
add_tree(u,v,w) ;
}
}
scanf("%d", &q) ;
while( q-- ) {
scanf("%d %d", &u, &v) ;
u = belong[u] ;
v = belong[v] ;
w = spfa(u,v) ;
if( w == INF )
printf("Nao e possivel entregar a carta\n") ;
else
printf("%d\n", w) ;
}
printf("\n") ;
}
return 0 ;
}