题解 P1674
模拟赛 C 题解(洛谷 P1674)
\[\]
先二分确定最小长度,设值为 \(mid\),那么大于 \(mid\) 长度的道路都不用考虑了,只考虑不大于 \(mid\) 的道路。
因为这些道路最多只能走一次,所以容量为 \(1\),因为需要走 \(k\) 次,所以只需看这些道路组成的无向图最大流是否 \(\ge k\) 即可。(注意,因为无向图,所以反边容量也为 \(1\))
#include <iostream>
#include <queue>
#include <cstring>
using namespace std;
int n,m,ans2,s,t,k,e[205][205],zkr[100005],vis[100005],cur[100005],din[1000005],nxt[1000005],id = 1;
struct node
{
int v,w;
}ve[1000005];
void add(int x,int y,int z)
{
ve[++id] = {y,z},nxt[id] = din[x];
din[x] = id;
}
bool bfs()
{
queue<int>q;
while(!q.empty())q.pop();
fill(zkr,zkr + n + 7,1e9);
zkr[s] = 0;
q.push(s);
while(!q.empty())
{
int tmp = q.front();
q.pop();
for(int i = din[tmp];i;i = nxt[i])
{
int to = ve[i].v;
if(!ve[i].w || zkr[to] <= zkr[tmp] + 1)continue ;
zkr[to] = zkr[tmp] + 1;
q.push(to);
}
}
if(zkr[t] > 5e8)return 0;
return 1;
}
int get_Zeng(int x,int opval)
{
if(!opval)return 0;
if(x == t)return opval;
int cnt = opval;
for(int i = cur[x];i;i = nxt[i])
{
int to = ve[i].v;
if(zkr[to] == zkr[x] + 1)
{
int liu = get_Zeng(to,min(opval,ve[i].w));
ve[i].w -= liu,ve[i ^ 1].w += liu,opval -= liu;
if(!opval)return cnt;
}
cur[x] = i;
}
return cnt - opval;
}
int Dinic()
{
int liu = 0;
while(bfs())
{
memcpy(cur,din,sizeof(cur));
int anw = 1e9;
while(anw)
{
anw = get_Zeng(s,1e9);
liu += anw;
}
}
return liu;
}
int U[50005],V[50005],W[50005];
bool check(int mi)
{
fill(din,din + id + 3,0);
fill(nxt,nxt + id + 3,0);
id = 1;
for(int i = 1;i <= m;i ++)
if(W[i] <= mi)add(U[i],V[i],1),add(V[i],U[i],1);
return Dinic() >= k;
}
int main()
{
cin >> n >> m >> k;
s = 1,t = n;
for(int i = 1;i <= m;i ++)cin >> U[i] >> V[i] >> W[i];
int l = 1,r = 1000000;
while(l < r)
{
int mid = (l + r) >> 1;
if(check(mid))r = mid;
else l = mid + 1;
}
cout << l;
}

浙公网安备 33010602011771号