BZOJ 1614 [Usaco2007 Jan]Telephone Lines架设电话线:spfa + 二分【路径中最大边长最小】

题目链接: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 }

 

posted @ 2017-09-28 20:57  Leohh  阅读(190)  评论(0编辑  收藏  举报