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)