好题!...(躺)
一开始推个分层图最短路...然后发现并不是求最短路(躺
这题题目大意我没看错应该是这样的:
找一条1~n的路径,使路径上第k+1大的数尽可能的小
这个提法是不是有点眼熟...
假设有这样一个问题:
找一条1~n的路径,使路径上最大的数最小
“使最大的最小”,二分答案!
然后我就不会了
hzwer有一个很妙的思路orz...
大概是这个意思吧...
二分一下路径上最大的边权mx,然后对最短路变一下形
把>mx的边权当做1,<=mx的边权当做0,因为>mx的肯定要用一次减免不然就超出当前的答案了
二分答案不就是假设当前是最优的答案来确定更优的答案的区间在哪...
然后check()就是判断dis[n]<=k?0:1
1 #include<cstdio> 2 #include<cstring> 3 #define inf 0x7fffffff 4 struct poi{int to,nxt,V;}e[20005]; 5 int cnt,head[1005]; 6 inline void add(int u,int v,int V){ 7 e[++cnt]=(poi){v,head[u],V}; 8 head[u]=cnt; 9 } 10 int dis[1005],q[10005]; 11 bool vis[1005]; 12 int n,m,k,ans; 13 inline int max(int a,int b){return a>b?a:b;} 14 inline int min(int a,int b){return a<b?a:b;} 15 void spfa(int u,int mx) { 16 for(int i=1;i<=n;i++) dis[i]=inf; 17 dis[1]=0; q[0]=u; vis[u]=1; 18 int t=0,w=1; 19 while(t!=w) { 20 int now=q[t++]; 21 for(int i=head[now];i;i=e[i].nxt) { 22 int to=e[i].to; 23 if((dis[now]+((e[i].V>mx)?1:0))<dis[to]) { 24 dis[to]=dis[now]+((e[i].V>mx)?1:0); 25 if(!vis[to]) { 26 vis[to]=1; q[w++]=to; 27 } 28 } 29 } 30 vis[now]=0; 31 } 32 } 33 inline bool check(int mx) { 34 spfa(1,mx); 35 return dis[n]<=k; 36 } 37 int main() { 38 scanf("%d%d%d",&n,&m,&k); 39 int l=0,r=0; 40 for(int i=1;i<=m;i++) { 41 int u,v,V; 42 scanf("%d%d%d",&u,&v,&V); 43 if(u==v) continue; 44 add(u,v,V); add(v,u,V); 45 r=max(r,V); 46 } 47 ans=-1; 48 while(l<=r) { 49 int mid=(l+r) >> 1; 50 if(check(mid)){ans=mid;r=mid-1;} 51 else l=mid+1; 52 } 53 printf("%d\n",ans); 54 }
原文地址:https://www.cnblogs.com/ZincSabian/p/9367749.html
时间: 2024-11-05 18:45:09