------------7题弟弟,被各位半小时13题的大佬打惨了(滑稽)----------
签到题就不写了。
F :Moving On (1247ms)
题意:给定大小为N的带点权,带边权的完全图,N<200。 然后Q次询问,每次给出(u,v,w),让你求在除了起点终点的其他途经点的点权都<=w的条件下的最短路。
思路:可以离线做的话,显然就是需要排序了。 然后想到floyd就是一个用点更新的最短路算法。 那么我们把floyd的第一层按点权排个序即可。 那么第k层的dis[i][j],就表示途经点都<=w[k]的最短路。 为了方便,这里所有的点权和询问的w都离散化了。 (比赛因为没有初始化WA了半天,哭)(网上看了其他人的写法大都是三维的,显然没必要,很明显是滚动的,在可以离线的情况下,第一维没什么用)。
#include<bits/stdc++.h> #define pii pair<int,int> #define rep(i,a,b) for(int i=a;i<=b;i++) using namespace std; const int maxn=210; const int maxm=20010; int mp[maxn][maxn],b[maxn],tot,ans[maxm]; struct in{ int u,v,w,id; }; vector<in>G[maxn]; pii a[maxn]; int main() { int T,N,M,C=0; scanf("%d",&T); while(T--){ scanf("%d%d",&N,&M); rep(i,1,N) scanf("%d",&a[i].first),a[i].second=i; rep(i,1,N) b[i]=a[i].first; sort(b+1,b+N+1); tot=unique(b+1,b+N+1)-(b+1); rep(i,0,tot) G[i].clear(); rep(i,1,N) a[i].first=lower_bound(b+1,b+tot+1,a[i].first)-b; sort(a+1,a+N+1); rep(i,1,N) rep(j,1,N) scanf("%d",&mp[i][j]); rep(i,1,M) { in t; scanf("%d%d%d",&t.u,&t.v,&t.w); ans[i]=mp[t.u][t.v]; t.w=upper_bound(b+1,b+tot+1,t.w)-b; t.w--; t.id=i; G[t.w].push_back(t); } rep(k,1,N) { int tk=k; while(tk+1<=N&&a[tk+1].first==a[k].first) tk++; rep(p,k,tk) { rep(i,1,N) rep(j,1,N){ int kk=a[p].second; mp[i][j]=min(mp[i][j],mp[i][kk]+mp[kk][j]); } } for(int i=0;i<G[a[k].first].size();i++){ in t=G[a[k].first][i]; ans[t.id]=min(ans[t.id],mp[t.u][t.v]); } k=tk; } printf("Case #%d:\n",++C); rep(i,1,M) printf("%d\n",ans[i]); } return 0; }