题目链接:
题目大意:
有V个点,N个队伍,E条边,经过每条边有个时间,告诉你初始N个队伍的位置,求至少有K个队伍在不同的点的最短时间
题解:
我们二分答案时间,显然具有单调性。先floyd预处理两点之间的最短路,二分答案后把每个人和他可以走到的点连起来,跑一次最大匹配。若最大匹配数大于等于k,说明当前答案小了,否则大了
(每个匹配相等于一个人和他最终去的位置)
#include#include #include #include using namespace std;const int N=600+15;const int inf=1e9+7;const int Inf=1731311;int v,e,n,k;int pos[N],d[N][N],mp[N][N],match[N],vis[N];inline int read(){ char ch=getchar(); int s=0,f=1; while (ch<'0'||ch>'9') { if (ch=='-') f=-1;ch=getchar();} while (ch>='0'&&ch<='9') {s=(s<<3)+(s<<1)+ch-'0';ch=getchar();} return s*f;}void floyd(){ for (int k=1;k<=v;k++) for (int i=1;i<=v;i++) for (int j=1;j<=v;j++) d[i][j]=min(d[i][j],d[i][k]+d[k][j]);}bool dfs(int x){ for (int i=1;i<=v;i++) { if (vis[i]||!mp[x][i]) continue; vis[i]=1; if (match[i]==-1||dfs(match[i])) { match[i]=x; return true; } } return false;}int check(int l){ memset(match,-1,sizeof(match)); for (int i=1;i<=n;i++) for (int j=1;j<=v;j++) mp[i][j]=(d[pos[i]][j]<=l); int ans=0; for (int i=1;i<=n;i++) { memset(vis,0,sizeof(vis)); if (dfs(i)) ans++; } return ans; }int main(){ v=read();e=read();n=read();k=read(); for (int i=1;i<=v;i++) for (int j=1;j<=v;j++) if (i!=j) d[i][j]=inf; for (int i=1;i<=n;i++) pos[i]=read(); for (int i=1,u,v,w;i<=e;i++) { u=read();v=read();w=read(); d[u][v]=d[v][u]=min(d[u][v],w); } floyd(); int l=0,r=Inf,ans=Inf; while (l >1; if (check(mid)>=k) r=mid,ans=min(ans,r); else l=mid+1; } if (ans==Inf) puts("-1"); else printf("%d\n",ans); return 0;}