题目大意:
n个间谍 他们之间传送信息需要一定的时间一个联通分量里面的间谍属于一个国家,之间的信息传递不需要时间然后问你从一个间谍传一个信息到另一个间谍那需要最少时间 也可能传不到
思路:先缩点,再最短路,由于n最大只有500.可以用邻接矩阵,而且对缩点后的DAG的边权可以做贪心处理,只留两个强连通分量间的最短边长即可。
//2852K 297MS C++ 2595B #include<cstdio> #include<iostream> #include<cstring> #include<algorithm> using namespace std; #define min(a,b) (a<b? a:b); const int N = 555; const int inf = 0x3f3f3f3f; int n,m,sccnum; int mp[N][N]; int head[N]; int col[N]; struct Edge { int v,w,next; }es[N*N]; int index; int dfn[N],low[N]; int tmp[N],sta[N],top; void tarjan(int u) { dfn[u]=low[u]=++index; tmp[u]=1; sta[++top]=u; for(int i=head[u];~i;i=es[i].next) { int v=es[i].v; if(tmp[v]==0) tarjan(v); if(tmp[v]==1) low[u]=min(low[u],low[v]); } if(low[u]==dfn[u]) { sccnum++; while(1) { int v=sta[top]; col[v]=sccnum; tmp[v]=2; if(sta[top--]==u) break; } } } bool vis[N]; int dis[N]; void dijkstra(int src,int n) { for(int i=1;i<=n;i++) dis[i]=inf,vis[i]=0; dis[src]=0; while(true) { int v=-1; for(int i=1;i<=n;i++) if(vis[i]==0&&(v==-1||dis[i]<dis[v])) v=i; if(v==-1) break; vis[v]=1; for(int i=1;i<=n;i++) if(mp[v][i]!=inf) dis[i]=min(dis[i],dis[v]+mp[v][i]); } } void ini() { memset(head,-1,sizeof(head)); memset(tmp,0,sizeof(tmp)); memset(dfn,0,sizeof(dfn)); memset(col,0,sizeof(col)); sccnum=top=index=0; } int main() { int cas=0; while(scanf("%d%d",&n,&m),n) { if(cas!=0) puts(""); cas++; ini(); for(int i=1;i<=m;i++) { int u,v,w; scanf("%d%d%d",&u,&v,&w); es[i].v=v; es[i].w=w; es[i].next=head[u]; head[u]=i; } for(int i=1;i<=n;i++) if(dfn[i]==0) tarjan(i); memset(mp,0x3f,sizeof(mp)); for(int u=1;u<=n;u++) for(int i=head[u];~i;i=es[i].next) { int v=es[i].v,w=es[i].w; if(col[v]==col[u]) continue; mp[col[u]][col[v]]=min(mp[col[u]][col[v]],w); } int op; scanf("%d",&op); while(op--) { int s,g; scanf("%d%d",&s,&g); if(col[s]==col[g]) puts("0"); else { dijkstra(col[s],sccnum); if(dis[col[g]]==inf) puts("Nao e possivel entregar a carta"); else printf("%d\n",dis[col[g]]); } } } return 0; }
时间: 2024-12-09 08:20:09