题目大意:
给出一个带权有向图,将其中的强连通分量缩成点,再求最短路。若有输出最小值,若没有输出:“Nao e possivel entregar a carta” (“It’s impossible to deliver the letter”).
解题思路:
1、建图,然后Tarjan算法缩点。
2、求最短路然后输出。
下面是代码:
#include <stdio.h> #include <string.h> #include <queue> 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],stack1[MAXN],head[MAXN],top,time,cnt; int num[MAXN],numcnt; int nhead[MAXN],ncnt; int dis[MAXN]; int n,m; void init() { memset(dfn,0,sizeof(dfn)); memset(low,0,sizeof(low)); memset(vis,0,sizeof(vis)); memset(num,0,sizeof(num)); memset(head,-1,sizeof(head)); memset(nhead,-1,sizeof(nhead)); memset(stack1,0,sizeof(stack1)); ncnt=0; top=0; cnt=0; time=1; 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++; } int min(int a , int b) { if(a>b)a=b; return a; } void dfs(int u,int fa) { dfn[u]=time; low[u]=time; time++; vis[u]=1; stack1[top]=u; top++; for(int i = head[u] ; i != -1 ; i = edge[i].next) { int v=edge[i].v; if(!vis[v]) { dfs(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]) { while(stack1[top]!=u&&top>0) { top--; num[stack1[top]]=numcnt; vis[stack1[top]]=2; } numcnt++; } } void Tarjan() { for(int i = 1 ; i<=n; i++) { if(!vis[i])dfs(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(num[i]!=num[v]) { Readdedge(num[i],num[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(); int p = nhead[t]; vis[t]=0; q.pop(); while(p!=-1) { int v = nedge[p].v; int w = nedge[p].w; if(dis[v]>dis[t]+w) { dis[v]=dis[t]+w; if(!vis[v]) { q.push(v); vis[v]=1; } } p=nedge[p].next; } } 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(num[u]==num[v]) { puts("0"); continue; } spfa(num[u],num[v]); } } int main() { while(scanf("%d%d",&n,&m),n) { init(); Build(); Tarjan(); ReBuild(); Ask(); puts(""); } return 0; }