题目链接:http://poj.org/problem?id=3114
题意:给你n个城市和m条边以及其权值,然后有一个条件是如果两个城市互相能够到达对方则他们属于同一个国家,如果在一个国家里的两个城市就算他们的边权不为0,他们通信也是0消耗,也就是说在一个强联通分量中的两点通信就是0消耗,那么我们就可以先进行一次强联通缩点建立DAG图,我们再计算在DAG点之间的最短距离,这个题的数据似乎用Floyd不会超时,但是小编还是稳一步用SPFA来解决。
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <queue>
#include <stack>
using namespace std;
const int MAXN = 505;
const int inf = 1<<30;
struct node
{
int v,w,next;
}edge[MAXN*MAXN],nedge[MAXN*MAXN];
int DFN[MAXN],Low[MAXN],vis[MAXN],index;
int belong[MAXN],numcnt;
int head[MAXN],cnt,nhead[MAXN],ncnt;
int dis[MAXN];
int n,m;
stack<int> S;
void init()
{
memset(DFN,0,sizeof(DFN));
memset(Low,0,sizeof(Low));
memset(vis,0,sizeof(vis));
memset(belong,0,sizeof(belong));
memset(head,-1,sizeof(head));
memset(nhead,-1,sizeof(nhead));
ncnt = cnt = 0;
index = numcnt = 1;
}
void addedge(int u,int v,int w)
{
edge[cnt].v=v;
edge[cnt].w=w;
edge[cnt].next=head[u];
head[u]=cnt;
cnt++;
}
void Tarjan(int u,int fa)
{
int v;
DFN[u] = Low[u] = index++;
vis[u]=1;
S.push(u);
for(int i=head[u]; i!=-1; i=edge[i].next)
{
v=edge[i].v;
if(!DFN[v])
{
Tarjan(v,u);
Low[u] = min(Low[u],Low[v]);
}
else if(vis[v]==1)
Low[u] = min(Low[u],DFN[v]);
}
if(DFN[u]==Low[u])
{
do
{
v = S.top();
S.pop();
belong[v]=numcnt;
vis[v]=2;
}while(u != v);
numcnt++;
}
}
void SCC()
{
for(int i = 1 ; i<=n; i++)
if(!DFN[i])
Tarjan(i,0);
}
void Build()
{
int u,v,w;
for(int i = 0 ; i < m ; i ++ )
{
scanf("%d%d%d",&u,&v,&w);
addedge(u,v,w);
}
}
void Readdedge(int u ,int v ,int w)
{
nedge[ncnt].v=v;
nedge[ncnt].w=w;
nedge[ncnt].next=nhead[u];
nhead[u]=ncnt;
ncnt++;
}
void ReBuild()
{
for(int i=1; i<=n ;i++ )
{
for(int j=head[i]; j!=-1 ; j=edge[j].next )
{
int v=edge[j].v;
if(belong[i] != belong[v])
{
Readdedge(belong[i],belong[v],edge[j].w);
}
}
}
}
void spfa(int start,int end)
{
queue<int> q;
for(int i=1; i<numcnt; i++)
{
dis[i]=inf;
vis[i]=0;
}
dis[start]=0;
vis[start]=1;
q.push(start);
while(!q.empty())
{
int t = q.front();
vis[t]=0;
q.pop();
for(int i=nhead[t]; i!=-1; i=nedge[i].next)
{
int v = nedge[i].v;
int w = nedge[i].w;
if(dis[v]>dis[t]+w)
{
dis[v]=dis[t]+w;
if(!vis[v])
{
q.push(v);
vis[v]=1;
}
}
}
}
if(dis[end]!=inf)
printf("%d\n",dis[end]);
else
printf("Nao e possivel entregar a carta\n");
}
void Ask()
{
int k,u,v;
scanf("%d",&k);
while(k--)
{
scanf("%d%d",&u,&v);
if(belong[u] == belong[v])
puts("0");
else
spfa(belong[u],belong[v]);
}
}
int main()
{
while(scanf("%d%d",&n,&m),n)
{
init();
Build();
SCC();
ReBuild();
Ask();
puts("");
}
return 0;
}