题目:http://www.qscoj.cn/#/problem/show/1955
我们可以先用spfa跑出每2个点之间的距离
之后枚举b点和c点,再枚举从c点出发和到达b点的最大距离
对距离排序后先找到的答案更优,所以找到后就可以退出循环
#include<iostream> #include<cstdio> #include<cstring> #include<string> #include<cmath> #include<algorithm> #include<vector> #include<queue> #include<stack> #include<map> #include<set> using namespace std; const int N=1e5+5; int head[N],to[N],val[N],nt[N],d[1005][1005]; bool vis[N]; int tot; void addedge(int u,int v,int w) { nt[++tot]=head[u]; val[tot]=w; to[tot]=v; head[u]=tot; } void spfa(int x) { memset(d[x],0x3f,sizeof(d[x])); memset(vis,0,sizeof(vis)); queue<int> que; que.push(x); d[x][x]=0; while(!que.empty()) { int t=que.front();que.pop(); vis[t]=0; for(int i=head[t];i!=-1;i=nt[i]) if (d[x][to[i]]>d[x][t]+val[i]) { d[x][to[i]]=d[x][t]+val[i]; if (!vis[to[i]]) { que.push(to[i]); vis[to[i]]=1; } } } } struct p { int x,y; p(int xx,int yy) { x=xx; y=yy; } bool operator >(p t)const { return y>t.y; } }; vector<p> a[N],b[N]; int main() { int n,m; scanf("%d%d",&n,&m); memset(head,-1,sizeof(head)); tot=0; for(int i=1;i<=m;i++) { int x,y,z; scanf("%d%d%d",&x,&y,&z); addedge(x,y,z); } for(int i=1;i<=n;i++) spfa(i); for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) if (i!=j) { if (d[i][j]!=0x3f3f3f3f) a[i].push_back(p(j,d[i][j])); if (d[j][i]!=0x3f3f3f3f) b[i].push_back(p(j,d[j][i])); } for(int i=1;i<=n;i++) { sort(a[i].begin(),a[i].end(),greater<p>()); sort(b[i].begin(),b[i].end(),greater<p>()); } int ans=0; int aa,bb,cc,dd; for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) { if (i!=j&&d[i][j]!=0x3f3f3f3f) for(int ii=0;ii<b[i].size();ii++) { int flag=0; for(int jj=0;jj<a[j].size();jj++) if (b[i][ii].x!=a[j][jj].x&&b[i][ii].x!=j&&a[j][jj].x!=i) { int t=b[i][ii].y+a[j][jj].y+d[i][j]; if (t>ans) { ans=t; aa=b[i][ii].x; bb=i; cc=j; dd=a[j][jj].x; } flag=1; break; } if (flag) break; } } printf("%d %d %d %d ",aa,bb,cc,dd); return 0; }