【BubbleCup X】D. Exploration plan
这个题首先一眼能看出二分答案……
毕竟连可爱的边界都给你了。
下面就是怎么check
首先预处理跑一遍floyed,预处理出最短路。
用网络流判断能否达到即可。
#include<bits/stdc++.h> typedef long long ll; const int N=2010; const int M=1000005; const int inf=1e9+7; using namespace std; inline int read(){ int f=1,x=0;char ch; do{ch=getchar();if(ch=='-')f=-1;}while(ch<'0'||ch>'9'); do{x=x*10+ch-'0';ch=getchar();}while(ch>='0'&&ch<='9'); return f*x; } namespace MaxFlow{ struct Edge{int u,v,next,f;}G[M]; int head[N],level[N],tot; inline void init(){tot=1;memset(head,0,sizeof(head));} inline void addedge(int u,int v,int f){ G[++tot].u=u;G[tot].v=v;G[tot].f=f;G[tot].next=head[u];head[u]=tot; G[++tot].u=v;G[tot].v=u;G[tot].f=0;G[tot].next=head[v];head[v]=tot; } inline bool bfs(int s,int t){ memset(level,0,sizeof(level));queue<int>q; q.push(s);level[s]=1; while(!q.empty()){ int u=q.front();q.pop(); if(u==t)return 1; for(int i=head[u];i;i=G[i].next){ int v=G[i].v,f=G[i].f; if(f&&!level[v])level[v]=level[u]+1,q.push(v); } } return 0; } inline int dfs(int u,int maxf,int t){ if(u==t)return maxf;int rat=0; for(int i=head[u];i;i=G[i].next){ int v=G[i].v,f=G[i].f; if(f&&level[v]==level[u]+1){ f=dfs(v,min(maxf-rat,f),t); rat+=f;G[i].f-=f;G[i^1].f+=f; } } if(!rat)level[u]=inf; return rat; } inline int dinic(int s,int t){ int ans=0; while(bfs(s,t))ans+=dfs(s,inf,t); return ans; } } int n,m,p,q,f[N],dis[1010][1010]; inline bool check(int x){ MaxFlow::init();int s=0,t=n*2+1; for(int i=1;i<=n;i++)MaxFlow::addedge(s,i,f[i]); for(int i=1;i<=n;i++)MaxFlow::addedge(i+n,t,1); for(int i=1;i<=n;i++)if(f[i])for(int j=1;j<=n;j++) if(dis[i][j]<=x)MaxFlow::addedge(i,j+n,1); int ans=MaxFlow::dinic(s,t); return ans>=q; } int main(){ n=read();m=read();p=read();q=read(); for(int i=1;i<=p;i++){int x=read();f[x]++;} memset(dis,0x3f,sizeof(dis)); for(int i=1;i<=n;i++)dis[i][i]=0; for(int i=1;i<=m;i++){ int u=read(),v=read(),w=read();dis[u][v]=dis[v][u]=min(dis[u][v],w); } for(int k=1;k<=n;k++)for(int i=1;i<=n;i++)for(int j=1;j<=n;j++) dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]); int l=0,r=1731311,ret=-1; while(l<=r){ int mid=(l+r)>>1; if(check(mid))r=mid-1,ret=mid; else l=mid+1; } printf("%d\n",ret); }
zzq wc-ctsc-apio-NOI Au;yql精通多项式;zyz精通女装;由乃精通数据结构;孔老师是毒奶大师;我没有学上:我们都有光明的前途。