思路:先求出各个强联通分量,缩点,由于国家内部通信的不需要时间的,一个国内的某个城市和另一个国家内的某个城市通信等价与两个国家之间通信。
之后就是一套最短路的东西了,由于缩点之后是DAG,所以可以用DAG的最短路来求,但事实证明这个没有堆优化的dijkstra快。
#include<stdio.h>
#include<queue>
#include<string.h>
using namespace std;
const int N = 512;
const int INF = 0x3f3f3f3f;
int cnt, fir[N], fir1[N];
int dfn[N];
int low[N], stack1[N], stack2[N];
int dis[N][N];
int indeg[N];
int scc[N];
int myque[N];
int n, tstamp, sccNum, top1, top2, cnt1, qfront;
struct Edge {
int v, w, next;
};
struct Node {
int v, w;
Node() {};
Node(int pv, int pw):v(pv), w(pw) {};
bool operator < (const Node& other) const {
return w > other.w;
}
};
Edge edge[N*N];
Edge edge1[N*N];
void init() {
cnt = cnt1 = 0;
memset(fir, -1, sizeof(fir));
memset(fir1, -1, sizeof(fir1));
memset(indeg, 0, sizeof(indeg));
}
void addEdge(int u, int v, int w) {
edge[cnt].v = v;
edge[cnt].w = w;
edge[cnt].next = fir[u];
fir[u] = cnt++;
}
void addEdge1(int u, int v, int w) {
edge1[cnt1].v = v;
edge1[cnt1].w = w;
edge1[cnt1].next = fir1[u];
fir1[u] = cnt1++;
}
void gardfs(int cur) {
low[cur] = ++tstamp;
stack1[++top1] = cur;
stack2[++top2] = cur;
for(int i = fir[cur]; i != -1; i = edge[i].next) {
int v = edge[i].v;
if(!low[v]) {
gardfs(v);
} else if(!scc[v]) {
while(low[stack2[top2]] > low[v])
top2--;
}
}
if(stack2[top2] == cur) {
top2--;
sccNum++;
do {
scc[stack1[top1]] = sccNum;
} while(stack1[top1--] != cur);
}
}
void garbow() {
memset(low, 0, sizeof(low));
memset(scc, 0, sizeof(scc));
top1 = top2 = tstamp = sccNum = 0;
for(int i = 1; i <= n; i++)
if(!low[i]) gardfs(i);
}
void dijkstra(int s) {
priority_queue<Node> pque;
dis[s][s] = 0;
pque.push(Node(s, dis[s][s]));
while(!pque.empty()) {
Node cur = pque.top();
pque.pop();
for(int i = fir1[cur.v]; i != -1; i = edge1[i].next) {
int v = edge1[i].v;
if(dis[s][v] > dis[s][cur.v] + edge1[i].w) {
dis[s][v] = dis[s][cur.v] + edge1[i].w;
pque.push(Node(v, dis[s][v]));
}
}
}
}
void toposort() {
qfront = 1;
for(int i = 1; i <= sccNum; i++) {
if(indeg[i] == 0)
myque[qfront++] = i;
}
for(int i = 1; i <= sccNum; i++) {
for(int j = fir1[myque[i]]; j != -1; j = edge1[j].next) {
int v = edge1[j].v;
indeg[v]--;
if(indeg[v] == 0)
myque[qfront++] = v;
}
}
}
void DAGPath(int s) {
dis[s][s] = 0;
for(int i = 1; i < qfront; i++) {
for(int j = fir1[myque[i]]; j != -1; j = edge1[j].next) {
int v = edge1[j].v;
if(dis[s][v] > dis[s][myque[i]] + edge1[j].w) {
dis[s][v] = dis[s][myque[i]] + edge1[j].w;
}
}
}
}
int main() {
int m;
while(~scanf("%d%d", &n, &m), n) {
init();
for(int i = 0; i < m; i++) {
int u, v, w;
scanf("%d%d%d", &u, &v, &w);
addEdge(u, v, w);
}
garbow();
memset(dis, INF, sizeof(dis));
for(int i = 1; i <= n; i++) {
for(int j = fir[i]; j != -1; j = edge[j].next) {
int v = edge[j].v;
if(scc[i] != scc[v]) {
addEdge1(scc[i], scc[v], edge[j].w);
indeg[scc[v]] ++;
}
}
}
toposort();
for(int i = 1; i <= sccNum; i++) {
DAGPath(i);
//dijkstra(i);
}
int k;
scanf("%d", &k);
while(k--) {
int u, v;
scanf("%d%d", &u, &v);
if(scc[u] == scc[v]) {
printf("0\n");
continue;
}
if(dis[scc[u]][scc[v]] != INF) {
printf("%d\n", dis[scc[u]][scc[v]]);
} else printf("Nao e possivel entregar a carta\n");
}
printf("\n");
}
return 0;
}