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 }