在加权无向图上求出一条从1号结点到n号结点的路径,使路径上第k+1大的边权尽量小。
解读:二分搜索答案,求>mid的边的数量最好是k,否则就少一点点
#include<cstdlib>
#include<vector>
#include<queue>
#include<cstring>
using namespace std;
int n,m,k;
const int N=1003;
struct node
{
int v,w;
node(int vv,int ww)
{ v=vv,w=ww; }
node(){}
};
vector <node > g[N];
int sz[N];
struct nd
{
int v,d,cnt;
bool operator < (const nd & o) const
{ return d>o.d; }
nd(int vv,int dd,int c)
{ v=vv,d=dd,cnt=c; }
nd(){}
};
priority_queue <nd> q;
int dis[N][1003],mx;//就是求小于mid的边是不是 大于等于 k
bool check(int mid)
{
while(!q.empty() ) q.pop() ;
memset(dis,-1,sizeof(dis));
dis[1][0]=0,q.push(nd(1,0,0));
int ans=k+1;
while(!q.empty() )
{
nd t=q.top() ;q.pop() ;
if(t.d !=dis[t.v ][t.cnt ]) continue;
if(t.v ==n)
{
ans=t.cnt ;
break;
}
for(int i=0;i<sz[t.v ];i++)
{
int nx=g[t.v ][i].v ,dd,stp=t.cnt ;
if(g[t.v ][i].w > mid) dd=dis[t.v ][stp],stp++;
else dd=max(g[t.v ][i].w ,dis[t.v ][stp]);
if(stp>k) continue;
if(dd < dis[nx][stp] || dis[nx][stp]==-1)
{
dis[nx][stp]=dd;
q.push(nd(nx,dd,stp));
}
}
}
return ans<=k;
}
int main()
{
scanf("%d%d%d",&n,&m,&k);
int u,v,w;
while(m--)
{
scanf("%d%d%d",&u,&v,&w);
g[u].push_back(node(v,w));
g[v].push_back(node(u,w));
}
for(int i=1;i<=n;i++)
sz[i]=g[i].size() ;
int l=0,r=1<<30,ans;
if(!check(r))
printf("-1\n");
else
{
while(l<r)
{
int mid=(l+r)>>1;
if(check(mid)) r=mid;
else l=mid+1;
}
printf("%d\n",l);
}
return 0;
}
知识兔View Code