版权声明:转载请注明原出处啦QAQ(虽然应该也没人转载): https://blog.csdn.net/hzk_cpp/article/details/82960879
题目:poj3662.
题目大意:找一条从1到n的路径,使得这条路径上第k+1大的边最小.
解法一:
我们可以假装这是一张有向无环图DAG,那么我们就可以设计一个DP数组f[i][j]表示达到第i个点时免费维修了j条边的最小代价.
那么我们就可以发现方程即为:
.
但是这不是一张有向无环图,具有后效性,我们并不能这么跑一个DP.
所以我们用最短路代替DP,解决后效性的问题.
于是我们可以使用SPFA来做这道题,时间复杂度,其中若不特殊构造数据,则e为一个较小的常数.
代码如下:
//#include<bits/stdc++.h>
#include<iostream>
#include<queue>
using namespace std;
#define Abigail inline void
const int N=1000,M=10000;
const int INF=(1<<30)-1;
int n,m,k;
struct side{
int y,next,v;
}e[M*2+9];
int lin[N+9],top;
struct state{
int node,use;
};
queue<state>q;
int dis[N+9][M+9];
bool use[N+9][M+9];
void ins(int x,int y,int v){
e[++top].y=y;e[top].v=v;
e[top].next=lin[x];
lin[x]=top;
}
state make_state(int x,int y){
state t;
t.node=x,t.use=y;
return t;
}
void spfa(int sp,int sk){
for (int i=1;i<=n;i++)
for (int j=0;j<=k;j++)
dis[i][j]=INF;
q.push(make_state(sp,sk));
dis[sp][sk]=0;
use[sp][sk]=1;
while (!q.empty()){
state t=q.front();
q.pop();use[t.node][t.use]=0;
for (int i=lin[t.node];i;i=e[i].next){
if (max(dis[t.node][t.use],e[i].v)<dis[e[i].y][t.use]){
dis[e[i].y][t.use]=max(dis[t.node][t.use],e[i].v);
if (!use[e[i].y][t.use]){ //这里不能用continue代替,否则下面的语句就不会运行
use[e[i].y][t.use]=1;
q.push(make_state(e[i].y,t.use));
}
}
if (t.use<k&&dis[t.node][t.use]<dis[e[i].y][t.use+1]){
dis[e[i].y][t.use+1]=dis[t.node][t.use];
if (!use[e[i].y][t.use+1]){
use[e[i].y][t.use+1]=1;
q.push(make_state(e[i].y,t.use+1));
}
}
}
}
}
Abigail into(){
scanf("%d%d%d",&n,&m,&k);
int x,y,l;
for (int i=1;i<=m;i++){
scanf("%d%d%d",&x,&y,&l);
ins(x,y,l);ins(y,x,l);
}
}
Abigail work(){
spfa(1,0);
}
Abigail outo(){
if (dis[n][k]^INF) printf("%d\n",dis[n][k]);
else printf("-1\n");
}
int main(){
into();
work();
outo();
return 0;
}
解法二:
我们可以很容易发现这道题中,若我们花费的钱更多时,那么合法的方案已定越多,且已定包含花费更少的方案,所以我们发现这道题可以使用二分花费转化为判定问题.
我们确定一个花费mid后,我们可以将大于这个花费的边的边权都设为1,小于的都设为0,那么我们就可以跑一遍最短路.
由于这是0-1边权最短路问题,所以我们可以使用一个双端队列BFS来进行求解.
双端队列BFS的时间复杂度为,二分的时间复杂度为,所以总的时间复杂度即为.
代码如下:
//#include<bits/stdc++.h>
#include<iostream>
#include<deque>
using namespace std;
#define Abigail inline void
typedef long long LL;
const int N=1000,M=10000;
const int INF=(1<<20)-1;
int n,m,k;
struct side{
int y,next,v,use;
}e[M*2+9];
int top,lin[N+9];
int dis[N+9],use[N+9],ans;
deque<int>q;
void ins(int x,int y,int v){
e[++top].y=y;e[top].v=v;
e[top].next=lin[x];
lin[x]=top;
}
bool check(int mid){
for (int i=1;i<=top;i++)
e[i].use=e[i].v>mid?1:0;
for (int i=1;i<=n;i++)
use[i]=0,dis[i]=INF;
dis[1]=0;use[1]=1;
q.push_back(1);
while (!q.empty()){
int t=q.front();
q.pop_front();use[t]=2;
for (int i=lin[t];i;i=e[i].next)
if (dis[t]+e[i].use<dis[e[i].y]){
dis[e[i].y]=dis[t]+e[i].use;
if (use[e[i].y]) continue;
use[e[i].y]=1;
if (e[i].use) q.push_back(e[i].y);
else q.push_front(e[i].y);
}
}
return dis[n]<=k;
}
Abigail into(){
scanf("%d%d%d",&n,&m,&k);
int x,y,v;
for (int i=1;i<=m;i++){
scanf("%d%d%d",&x,&y,&v);
ins(x,y,v);ins(y,x,v);
}
}
Abigail work(){
ans=INF;
for (int i=19;i>=0;i--)
if (check(ans-(1<<i))) ans-=1<<i;
}
Abigail outo(){
printf("%d\n",ans^INF?ans:-1);
}
int main(){
into();
work();
outo();
return 0;
}