题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1614
题意:
给你一个无向图,n个点,m条边。
你需要找出一条从1到n的路径,使得这条路径上去掉k条最大的边后,剩余边中最大的边最小。
问你最大边最小为多少。
题解:
求最大值最小:二分。
二分:最大边的值L。
check函数:
每次一遍spfa。
对于每条边,如果len > L,则认为该边边权为1;如果len <= L,则边权为0。
dis[i]也就代表:从1到i最少要去掉多少条边,才能使答案为L。
所以答案为:令dis[n] <= k的最小的L。
AC Code:
1 #include <iostream> 2 #include <stdio.h> 3 #include <string.h> 4 #include <vector> 5 #include <queue> 6 #define MAX_N 1005 7 #define INF 10000000 8 9 using namespace std; 10 11 struct Edge 12 { 13 int dest; 14 int len; 15 Edge(int _dest,int _len) 16 { 17 dest=_dest; 18 len=_len; 19 } 20 Edge(){} 21 }; 22 23 int n,m,k; 24 int ans=-1; 25 int dis[MAX_N]; 26 bool vis[MAX_N]; 27 vector<Edge> edge[MAX_N]; 28 queue<int> q; 29 30 void read() 31 { 32 cin>>n>>m>>k; 33 int a,b,v; 34 for(int i=0;i<m;i++) 35 { 36 cin>>a>>b>>v; 37 edge[a].push_back(Edge(b,v)); 38 edge[b].push_back(Edge(a,v)); 39 } 40 } 41 42 int get_front() 43 { 44 int now=q.front(); 45 q.pop(); 46 vis[now]=false; 47 return now; 48 } 49 50 void insert(int now) 51 { 52 if(vis[now]) return; 53 q.push(now); 54 vis[now]=true; 55 } 56 57 void spfa(int start,int maxl) 58 { 59 memset(dis,-1,sizeof(dis)); 60 memset(vis,false,sizeof(vis)); 61 insert(start); 62 dis[start]=0; 63 while(!q.empty()) 64 { 65 int now=get_front(); 66 for(int i=0;i<edge[now].size();i++) 67 { 68 Edge temp=edge[now][i]; 69 if(dis[temp.dest]==-1 || dis[temp.dest]>dis[now]+(temp.len>maxl)) 70 { 71 dis[temp.dest]=dis[now]+(temp.len>maxl); 72 insert(temp.dest); 73 } 74 } 75 } 76 } 77 78 void solve() 79 { 80 int lef=0; 81 int rig=INF; 82 while(rig-lef>1) 83 { 84 int mid=(lef+rig)/2; 85 spfa(1,mid); 86 if(dis[n]==-1) return; 87 if(dis[n]>k) lef=mid; 88 else rig=mid; 89 } 90 spfa(1,lef); 91 if(dis[n]<=k) ans=lef; 92 else ans=rig; 93 } 94 95 void print() 96 { 97 cout<<ans<<endl; 98 } 99 100 int main() 101 { 102 read(); 103 solve(); 104 print(); 105 }