標籤:ace continue target tchar check get puts div put
題目連結:http://codeforces.com/problemset/problem/852/D題目大意:
有V個點,N個隊伍,E條邊,經過每條邊有個時間,告訴你初始N個隊伍的位置,求至少有K個隊伍在不同的點的最短時間
題解:
我們二分答案時間,顯然具有單調性。先floyd預先處理兩點之間的最短路,二分答案後把每個人和他可以走到的點連起來,跑一次最大匹配。若最大匹配數大於等於k,說明當前答案小了,否則大了
(每個匹配相等於一個人和他最終去的位置)
#include<algorithm>#include<cstring>#include<iostream>#include<cstdio>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<r) { int mid=l+r>>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;}
[codeforces 852 D] Exploration Plan 解題報告 (二分+最大匹配)