CDQZ_Training 2012-05-24 笨笨的电话网络

题目:   时间限制:
10000ms
内存限制:
128000kB
描述

多年以后,笨笨长大了,成为了电话线布置帅。由于地震使得某市的电话线全部损坏,笨笨是负责接到震中市的负责人、该市周围分布着N(1≤N≤1000)根据1..n顺序编号的废弃的电话线杆,任意两根线杆之间没有电话线连接,一共有p(1≤P≤10000)对电话杆可以拉电话线.其他的由于地震使得无法连接。

    第i对电线杆的两个端点分别是ai,bi,它们的距离为li(1≤li≤1000000)。数据中每对(ai,bi)只出现一次。编号为l的电话杆已经接入了全国的电话网络,整个市的电话线全都连到了编号N的电话线杆上。电就是说,笨笨的任务仅仅是找一条将1号和N号电线杆连起来的路径,其余的电话杆并不一定要连入电话网络。

    电信公司决定支援灾区免费为此市连接k(0≤k≤n)对由笨笨指定的电话线杆,对于此外的那些电话线,需要为它们付费,总费用决定于其中最长的电话线的长度(每根电话线仅连接一对电话线杆)。如果需要连接的电话线杆不超过k对,那么支出为0。

    请你计算一下,将电话线引到震中市最少需要在电话线上花多少钱7

 

输入
输入文件的第一行包含三个数字n,P,k;
第二行到第p+l行,每行分别都为三个整数al,bi,li。
输出
一个整数,表示陔项工程的最小支出,如果不可能完成则输出一l。
样例输入
 5 7 l
  1 2 5
  3 1 4
  2 4 8
  3 2 3
  5 2 9
  3 4 7
  4 5 6
样例输出 4   题解:   首先对全图进行一次bfs,检验0与-1的情况,这个应该非常好做吧……………………     然后我们二分一个权值,建设我们当前的权值为v。然后对全图进行spfa,此时我们对距离进行新的定义:两点之间的距离为这两点之间经过的边中权值大于v的条数。这样来对原图进行spfa,如果得到的dist[n]<=k,那么就说明当前的这个 权值v是一个可行的答案,并且比它小的也一定是可行解,于是二分答案即可。  
View Code
 1 #include<cstdio>
 2 #include<cstdlib>
 3 #include<cstring>
 4 #include<queue>
 5 
 6 using namespace std;
 7 
 8 const int maxn=1010;
 9 const int maxm=30000;
10 
11 int dist[maxn],n,m,k,en,max_v;
12 
13 bool use[maxn];
14 
15 queue<int> que;
16 
17 struct edge
18 {
19        int e,d;
20        edge *next;
21 }*v[maxn],ed[maxm];
22 
23 void add_edge(int s,int e,int d)
24 {
25      en++;
26      ed[en].next=v[s];v[s]=ed+en;v[s]->e=e;v[s]->d=d;
27 }
28 
29 void work(int nowd)
30 {
31      memset(dist,0x3f,sizeof(dist));
32      memset(use,false,sizeof(use));
33      use[1]=true;
34      dist[1]=0;
35      while (que.size())
36      que.pop();
37      que.push(1);
38      while (que.size())
39      {
40            int now=que.front();
41            que.pop();
42            use[now]=false;
43            for (edge *e=v[now];e;e=e->next)
44            {
45                if (e->d<=nowd && dist[e->e]>dist[now])
46                {
47                               dist[e->e]=dist[now];
48                               if (use[e->e]==false)
49                               {
50                                                    use[e->e]=true;
51                                                    que.push(e->e);
52                               }
53                }
54                if (e->d>nowd && dist[e->e]>dist[now]+1)
55                {
56                              dist[e->e]=dist[now]+1;
57                              if (use[e->e]==false)
58                              {
59                                                   use[e->e]=true;
60                                                   que.push(e->e);
61                              }
62                }
63            }
64      }
65 }
66 
67 int main()
68 {
69     scanf("%d%d%d",&n,&m,&k);
70     for (int a=1;a<=m;a++)
71     {
72         int s,e,d;
73         scanf("%d%d%d",&s,&e,&d);
74         add_edge(s,e,d);
75         add_edge(e,s,d);
76         max_v=max(max_v,d);
77     }
78     work(0);
79     if (dist[n]==dist[0]) printf("-1\n");
80     else
81     {
82         if (dist[n]<=k) printf("0\n");
83         else
84         {
85             int l=0,r=max_v;
86             while (l+1!=r)
87             {
88                   int m=(l+r)>>1;
89                   work(m);
90                   if (dist[n]<=k) r=m;
91                   else l=m;
92             }
93             printf("%d\n",r);
94         }
95     }
96     
97     return 0;
98 }

 

转载于:https://www.cnblogs.com/zhonghaoxi/archive/2012/05/25/2518523.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值