首页 > 代码库 > poj 3662 Telephone Lines spfa算法的灵活运用
poj 3662 Telephone Lines spfa算法的灵活运用
题意:
给一个有n个结点的无向图,要求一条从1到n的路径,你可以让其中的k条免费,这条路径的花费是这条路径上剩下的边中长度的最大值,现在要求花费的最小值。
思路:
这道题可以首先想到二分枚举路径上的最大值,我觉得用spfa更简洁一些。spfa的本质是一种搜索算法,既然是搜索,就涉及到状态的转移。在一般求最短路的spfa算法中,当到结点u时,对e(u,v)只需做如下转移:if(d[v]>d[u]+w(e)) d[v]=d[u]+w(e)。在跟一般的情况下,到结点u,对e(u,v)需做多种转移,比如这题中要考虑让e免费和不让e免费两种情况,具体的请参考实现。
代码:
//poj 3662 //sepNINE #include <iostream> #include <queue> using namespace std; const int maxN=1024; const int maxM=10024; struct Edge { int v,w,next; }edge[maxM*2]; struct Node { int u,used; }; int n,p,k,e; int head[maxN],dis[maxN][maxN],vis[maxN][maxN]; void spfa(int s,int t,int k) { queue<Node> Q; memset(vis,0,sizeof(vis)); int i,j; for(i=1;i<=n;++i) for(j=0;j<=k;++j) dis[i][j]=INT_MAX; Node x; x.u=s; x.used=0; dis[s][0]=0; vis[s][0]=1; Q.push(x); while(!Q.empty()){ Node x=Q.front(); int u=x.u,used=x.used; Q.pop(); vis[u][used]=0; for(int i=head[u];i!=-1;i=edge[i].next){ int v=edge[i].v,w=edge[i].w; if(used+1<=k&&dis[v][used+1]>dis[u][used]){//让这条边免费,免费的边数used要+1 dis[v][used+1]=dis[u][used]; if(vis[v][used+1]==0){ Node x; x.u=v;x.used=used+1; vis[x.u][x.used]=1; Q.push(x); } } if(dis[v][used]>max(dis[u][used],w)){//不让这条边免费,dis[v][used]为dis[u][used]和w中的最大值 dis[v][used]=max(dis[u][used],w); if(vis[v][used]==0){ Node x; x.u=v;x.used=used; vis[x.u][x.used]=1; Q.push(x); } } } } return ; } int main() { scanf("%d%d%d",&n,&p,&k); e=0; memset(head,-1,sizeof(head)); while(p--){ int a,b,c; scanf("%d%d%d",&a,&b,&c); edge[e].v=b;edge[e].w=c,edge[e].next=head[a];head[a]=e++; edge[e].v=a;edge[e].w=c;edge[e].next=head[b];head[b]=e++; } spfa(1,n,k); int ans=INT_MAX; for(int i=0;i<=k;++i) ans=min(ans,dis[n][i]); if(ans==INT_MAX) printf("-1"); else printf("%d",ans); return 0; }
poj 3662 Telephone Lines spfa算法的灵活运用
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。