P1948 [USACO08JAN]Telephone Lines S(二分&01bfs)

Posted Harris-H

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了P1948 [USACO08JAN]Telephone Lines S(二分&01bfs)相关的知识,希望对你有一定的参考价值。

P1948 [USACO08JAN]Telephone Lines S(二分&01bfs)

注意01bfs的方式。

如果要用vis数组,则判断的条件是这样。

if((d[v]<=d[u]+(w>x) && vis[v])) continue;

这里是与条件,因为可能存在v之前被访问过, v i s [ v ] = 1 vis[v]=1 vis[v]=1,但是 d [ v ] > d [ u ] + ( w > x ) d[v]>d[u]+(w>x) d[v]>d[u]+(w>x) 的情况,这种也要更新。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull; 
const int N=1e4+5,M=2e4+5,inf=0x3f3f3f3f,mod=1e9+7;
const int hashmod[4] = 402653189,805306457,1610612741,998244353;
#define mst(a,b) memset(a,b,sizeof a)
#define db double
#define PII pair<int,int>
#define PLL pair<ll,ll>
#define x first
#define y second
#define pb emplace_back
#define SZ(a) (int)a.size()
#define rep(i,a,b) for(int i=a;i<=b;++i)
#define per(i,a,b) for(int i=a;i>=b;--i)
#define ios ios::sync_with_stdio(false),cin.tie(nullptr) 
void Print(int *a,int n)
	for(int i=1;i<n;i++)
		printf("%d ",a[i]);
	printf("%d\\n",a[n]); 

template <typename T>		//x=max(x,y)  x=min(x,y)
void cmx(T &x,T y)
	if(x<y) x=y;

template <typename T>
void cmn(T &x,T y)
	if(x>y) x=y;

int n,p,k;
struct edge
	int to,nt,w;
e[N<<1];
int h[N],cnt;
void add(int u,int v,int w)
	e[++cnt]=v,h[u],w,h[u]=cnt;
	e[++cnt]=u,h[v],w,h[v]=cnt;


int d[N];
int vis[N];
bool ck(int x)
	deque<int>q;
	mst(d,0x3f);
	mst(vis,0);
	q.push_front(1);
	d[1] = 0;
	vis[1] = 1;
	while(!q.empty())
		int u = q.front();q.pop_front();
		//printf("u=%d\\n",u);
		for(int i=h[u];i;i=e[i].nt)
			int v = e[i].to,w=e[i].w;
			if((d[v]<=d[u]+(w>x) && vis[v])) continue;
			//printf("v=%d (%d,%d) %d %d\\n",v,d[v],d[u]+(w>x),d[v]<=d[u]+(w>x),vis[v]);
			vis[v] = 1;
			if(w<=x)
				d[v] = d[u];
				q.push_front(v);
			
			else 
				d[v] = d[u] + 1;
				q.push_back(v);
			
		
	
	return d[n]<=k;

int main()
	scanf("%d%d%d",&n,&p,&k);
	int mx =  0;
	rep(i,1,p)
		int u,v,w;
		scanf("%d%d%d",&u,&v,&w);
		add(u,v,w);
		cmx(mx,w);
	
	int l = 1,r=mx,ans=-1;
	while(l<=r)
		int m = l+r>>1;
		if(ck(m)) r=m-1,ans=m;
		else l=m+1;
	
	printf("%d\\n",ans);
	return 0;

不用vis的版本。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull; 
const int N=1e4+5,M=2e4+5,inf=0x3f3f3f3f,mod=1e9+7;
const int hashmod[4] = 402653189,805306457,1610612741,998244353;
#define mst(a,b) memset(a,b,sizeof a)
#define db double
#define PII pair<int,int>
#define PLL pair<ll,ll>
#define x first
#define y second
#define pb emplace_back
#define SZ(a) (int)a.size()
#define rep(i,a,b) for(int i=a;i<=b;++i)
#define per(i,a,b) for(int i=a;i>=b;--i)
#define IOS ios::sync_with_stdio(false),cin.tie(nullptr) 
void Print(int *a,int n)
	for(int i=1;i<n;i++)
		printf("%d ",a[i]);
	printf("%d\\n",a[n]); 

template <typename T>		//x=max(x,y)  x=min(x,y)
void cmx(T &x,T y)
	if(x<y) x=y;

template <typename T>
void cmn(T &x,T y)
	if(x>y) x=y;

int n,p,k;
struct edge
	int to,nt,w;
e[N<<1];
int h[N],cnt;
void add(int u,int v,int w)
	e[++cnt]=v,h[u],w,h[u]=cnt;
	e[++cnt]=u,h[v],w,h[v]=cnt;


int d[N];
bool ck(int x)
	deque<int>q;
	mst(d,0x3f);
	q.push_front(1);
	d[1] = 0;
	while(!q.empty())
		int u = q.front();q.pop_front();
		//printf("u=%d\\n",u);
		for(int i=h[u];i;i=e[i].nt)
			int v = e[i].to,w=e[i].w;
			if(d[v]<=d[u]+(w>x)) continue;
			if(w<=x)
				d[v] = d[u];
				q.push_front(v);
			
			else 
				d[v] = d[u] + 1;
				q.push_back(v);
			
		
	
	return d[n]<=k;

int main()
	scanf("%d%d%d",&n,&p,&k);
	int mx =  0;
	rep(i,1,p)
		int u,v,w;
		scanf("%d%d%d",&u,&v,&w);
		add(u,v,w);
		cmx(mx,w);
	
	int l = 1,r=mx,ans=-1;
	while(l<=r)
		int m = l+r>>1;
		if(ck(m)) r=m-1,ans=m;
		else l=m+1;
	
	printf("%d\\n",ans);
	return 0;

分层图也可以做。

建立k+1层图。

然后跑dijkstra。

因为本题是求最长路的最小值,所以松弛的时候就d[v]>max(d[u],w),d[v]=max(d[u],w)

https://www.luogu.com.cn/blog/youngk/solution-p1948

以上是关于P1948 [USACO08JAN]Telephone Lines S(二分&01bfs)的主要内容,如果未能解决你的问题,请参考以下文章

P1948 [USACO08JAN]电话线Telephone Lines

洛谷P1948[USACO08JAN]电话线Telephone Lines

P1948 [USACO08JAN]Telephone Lines S(二分&01bfs)

P1948 [USACO08JAN]Telephone Lines S(二分&01bfs)

P1948 [USACO08JAN]电话线Telephone Lines

P1948 [USACO08JAN]电话线Telephone Lines spfa 二分答案