题解 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;
}
posted @ 2026-03-14 15:44  wuyixiang  阅读(9)  评论(0)    收藏  举报