标签:usaco queue max col span push class 分层图 情况
最短路
二分+SPFA
二分最小支出
如果边权<=最小支出,那么就相当于0
如果大于最小支出,值设为1
跑SPFA
如果dis[n] > k 说明到不了
否则说明可以到
模板套进去就好了,没什么好注释的...
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<cmath> #include<queue> using namespace std; const int INF=2e9+7; const int N=1e6+7; int n,m,k; int fir[N],from[N],to[N],val[N],cnt; inline void add(int a,int b,int c) { from[++cnt]=fir[a]; fir[a]=cnt; to[cnt]=b; val[cnt]=c; } int dis[1007]; bool vis[1007]; queue <int> q; bool SPFA(int mx) { memset(dis,0x7f,sizeof(dis)); memset(vis,0,sizeof(vis)); q.push(1); vis[1]=1; dis[1]=0; while(!q.empty()) { int u=q.front(); q.pop(); vis[u]=0; for(int i=fir[u];i;i=from[i]) { int v=to[i],cost= val[i]>mx ? 1 : 0; if(dis[v]>dis[u]+cost) { dis[v]=dis[u]+cost; if(!vis[v]) q.push(v),vis[v]=1; } } } return dis[n]>k ? 0 : 1; } int main() { int a,b,c,mx=-INF,mi=INF; cin>>n>>m>>k; for(int i=1;i<=m;i++) { scanf("%d%d%d",&a,&b,&c); add(a,b,c); add(b,a,c); mx=max(mx,c); mi=min(mi,c); } bool flag=0; while(mi<=mx) { int mid=(mi+mx)>>1; if(SPFA(mid)) mx=mid-1,flag=1; else mi=mid+1; } if(!flag) cout<<"-1"; else cout<<mi; return 0; }
还有一种很暴力的方法
分层图+SPFA
设dis [ i ] [ j ] 表示到了第 i 个点,用了 j 次免费次数时的最小支出
然后每次分为用免费次数和不用免费次数两种情况讨论,更新后面的dis
速度竟然差不多...
直接看代码就好了
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<cmath> #include<queue> using namespace std; const int N=1e6+7; int n,m,k; int fir[N],from[N],to[N],val[N],cnt; inline void add(int a,int b,int c) { from[++cnt]=fir[a]; fir[a]=cnt; to[cnt]=b; val[cnt]=c; } int dis[1007][1007]; bool vis[1007][1007]; struct node { int pos,num;//当前位置为pos,用了num次免费次数 }; queue <node> q; void SPFA() { memset(dis,0x7f,sizeof(dis)); q.push((node){1,0}); vis[0][0]=1; dis[1][0]=0; while(!q.empty()) { int pos=q.front().pos,num=q.front().num; q.pop(); vis[pos][num]=0; for(int i=fir[pos];i;i=from[i]) { int v=to[i],mx=max(dis[pos][num],val[i]); if( dis[v][num]>mx )//不用免费次数 { dis[v][num]=mx; if(!vis[v][num]) { q.push((node){v,num}); vis[v][num]=1; } } if(dis[v][num+1]>dis[pos][num]&&num<=k)//用免费次数 { dis[v][num+1]=dis[pos][num]; if(!vis[v][num+1]) { q.push((node){v,num+1}); vis[v][num+1]=1; } } } } } int main() { int a,b,c; cin>>n>>m>>k; for(int i=1;i<=m;i++) { scanf("%d%d%d",&a,&b,&c); add(a,b,c); add(b,a,c); } SPFA(); int ans=1e9+7; ans=min(ans,dis[n][k]); if(ans==1e9+7) cout<<"-1"; else cout<<ans; return 0; }
P1948 [USACO08JAN]电话线Telephone Lines
标签:usaco queue max col span push class 分层图 情况
原文地址:https://www.cnblogs.com/LLTYYC/p/9692191.html