题解CF852D勘探计划
【题意翻译】
给定一个\(五\)个点\(E\)条边的带权无向图,在图上有\(N\)个人,第\(i\)个人位于点\(x_
i\),一个人通过一条边需要花费这条边的边权的时间。
现在每个人可以自由地走。求最短多少时间后满足结束后有人的节点数\(\geq K\)
\(N,V \leq 500\)
【题目分析】
首先发现V很小,直接用\(弗洛伊德\)跑一遍全源最短路径。
然后考虑如何求时间,这个其实是图论中一个很经典的二分图论的模型,那么我们可以用一个二分寻找\(中\),连上所有长度\(\leq mid\)的边,用图论来\(检查\).
接下来就要选择图论使用的模型了。在一个图上,有一些人从一个点走向另一个点,很容易想到网络流中的最大流。由于每个点只要有人就行,那么让每个点向超级汇点\(t\)连一条容量为\(1\)的边,代表这个点对答案能产生\(1\)的流量,从超级源点\(s\)向每个点连一条容量为这个点人数的边,代表这个点能流出等同于这个点人数的流量,然后将\(\leq mid\)的边作为网络中的一条边,容量为\(inf\),跑最大流,判断是否\(\geq K\)。
\(tips:\)
建图的时候要拆点,拆成入口和出口,不然会出现流量分配的问题
每次支票记得记忆集
重边要取最小值
愉快的贴代码时间
#包括ebit/stdc .h
#定义inf 1e15
使用命名空间标准;
int read(){ 0
int w=0,h=1;char ch=getchar();
while(ch ' 0 ' | | ch ' 9 '){ if(ch=='-')h=-h;ch=getchar();}
while(ch=' 0 ' ch=' 9 '){ w=w * 10 ch-' 0 ';ch=getchar();}
返回w * h;
}
整数n,m,s,t,K,cnt,和;
int cow[610],谷仓[610];
int Floyd[610][610];
struct Dinic{
结构节点{
int旁边,cap,flow
} edge[3000010];
int head[10010],num
int cur[10010];
int dist[10010];
queueintq
void add(int u,int v,int cap,int flow){ 0
边[数]。next=head[u];
边[数]。to=v;
边[数]。cap=cap
边[数]。流量=流量;
head[u]=num;
返回;
}
void Add(int u,int v,int cap){ 0
add(u,v,cap,0);
add(v,u,0,0);
返回;
}
bool bfs(){ 0
memset(dist,0,sizeof(dist));
dist[s]=1;
q .推送;
while(!q . empty()){ 0
int u=q . front();
q . pop();
for(int I=head[u];我;i=edge[i].下一个){ 0
int v=edge[i].去;
if(!距离[v]边缘[i].卡佩治[我]。流量){ 0
dist[v]=dist[u]1;
q . push(v);
}
}
}
return dist[t];
}
int dfs(int u,int flow){ 0
if(u==t)回流;
int fl=0;
for(int I=cur[u];我;i=edge[i].下一个){ 0
cur[u]=I;
int v=edge[i].去;
if(dist[u] 1==dist[v]edge[i].卡佩治[我]。流量){ 0
int p=dfs(v,min(流量,边缘[i]).帽沿。流量));
if(p){ 0
边缘。流量=p;
edge[i^1].流量-=p;
流量-=p;
fl=p;
if(!流动)中断;
}
}
}
if(!fl)dist[u]=0;
返回fl;
}
int solve(){ 0
int flow=0;
while(bfs()){ 0
memcpy(cur,head,sizeof(cur));
int p;
而(p=dfs(s,1e9))流量=p;
}
回流;
}
void memst(){ 0
memset(head,0,sizeof(head));
num=1;
}
布尔检查(int x){ 0
memst();
for(int I=1;I=n;一)增加(1个n,t,1);
for(int I=1;I=n;I){ 0
如果(牛[i])加(s,I,牛[I]);
for(int j=1;j=n;j)
如果(弗洛伊德[i][j]=x)
添加(I,j n,1e 9);
}
返回求解()=K;
}
} ans
签名main(){ 0
n=read();m=read();CNT=read();k=read();
s=0;t=n n ^ 2;
memset(floyd,0x3f,sizeof(Floyd));
for(int I=1;i=cntI)奶牛[read()];
for(int I=1;I=n;(一)弗洛伊德[I][I]=0;
for(int I=1;I=m;I){ 0
int u=read(),v=read(),w=read();
弗洛伊德[u][v]=弗洛伊德[v][u]=min(弗洛伊德[u][v],w);
}
for(int k=1;k=n;k)
for(int I=1;I=n;(一)
for(int j=1;j=n;j)
弗洛伊德[I][j]=最小值(弗洛伊德[i][j],弗洛伊德[i][k]弗洛伊德[k][j]);
int l=0,r=1731311,RES=-1;
while(l=r){ 0
int mid=l r1
if(ans.check(mid))r=mid-1,res=mid
否则l=mid 1;
}
printf('%d\n ',RES);
返回0;
}
内容来源网络,如有侵权,联系删除,本文地址:https://www.230890.com/zhan/67469.html