题目描述如题。
思路:从某点可以无限次出发,很像流的问题,开始时候用流,不行。
如此抽象出来问题(问题抽象出来就简单了,关键是如何转化和抽象):这个最短时间,其实是所有点从起点出发,经过一条路径(至少吧),去汇集点的过程,那么最短的时间必然是最长的那条路径(时间最长),若无需攻占所有点,那么直接是最短里,所以要攻占所有点,必然是max(起点到i,i到终点)(遍历i)。
#include<iostream> #include<cstring> #include<cstdio> #include<queue> using namespace std; const int inf=0x3f3f3f3f; const int maxn=1001, maxe=200010; int head[maxn]; int nume=0;int e[maxe][3]; void inline adde(int i,int j,int w) { e[nume][0]=j;e[nume][1]=head[i];head[i]=nume; e[nume++][2]=w; e[nume][0]=i;e[nume][1]=head[j];head[j]=nume; e[nume++][2]=w; } int ds[maxn];int dt[maxn]; int n,m; void spfa(int s,int d[]) { int inq[maxn]; memset(inq,0,sizeof(inq)); d[s]=0; queue<int>q; q.push(s); while(!q.empty()) { int cur=q.front(); q.pop(); inq[cur]=0; for(int j=head[cur];j!=-1;j=e[j][1]) { int v=e[j][0]; if(d[v]>d[cur]+e[j][2]) { d[v]=d[cur]+e[j][2]; if(!inq[v]) { inq[v]=1; q.push(v); } } } } } int solve() { int minmax=0; for(int i=0;i<n;i++) { if(ds[i]+dt[i]>minmax) minmax=ds[i]+dt[i]; } return minmax; } void init() { nume=0; for(int i=0;i<n;i++) { head[i]=-1; ds[i]=inf; dt[i]=inf; } } int main() { int T; scanf("%d",&T);int ct=1; while(T--) { scanf("%d%d",&n,&m); init(); int aa,bb,cc; for(int i=0;i<m;i++) { scanf("%d%d%d",&aa,&bb,&cc); adde(aa,bb,cc); } int s,t; scanf("%d%d",&s,&t); spfa(s,ds); spfa(t,dt); int ans=solve(); printf("Case #%d: %d\n",ct++,ans); } return 0; }
时间: 2024-10-10 13:11:41