2.电话网络(phone.cpp/in/out)
[题目描述]
由于地震使得连接汶川县城电话线全部损坏,假如你是负责将电话线接到震中汶川县城的负责人,汶川县
城周围分布着N(1≤N≤1,000)根按1..N 顺次编号的废弃的电话线杆,任意两根电话线杆间都没有电话线相
连。一共P(1≤P≤10,000)对电话线杆间可以拉电话线,其余的由于地震使得无法被连接。
第i 对电话线杆的两个端点分别为Ai,Bi,它们间的距离为Li(1≤Li≤1,000,000)。数据中保证每对
(Ai,Bi)最多只出现1 次。编号为1 的电话线杆已经接人了全国的电话网络,整个县城的电话线全都连到了编
号为N 的电话线杆上。也就是说,你的任务仅仅是找一条将1 号和N 号电话线杆连起来的路径,其余的电话线
杆并不一定要连人电话网络。
电信公司决定支援灾区免费为汶川县城连结K(0≤K<N)对由你指定的电话线杆。对于此外的那些电话线,需要
为它们付费,总费用等于其中最长的电话线的长度(每根电话线仅连接一对电话线杆)。如果需要连接的电话线
杆不超过K 对,那么总支出为0。
请你计算一下,将电话线引到震中汶川县城最少需要在电话线上花多少钱?
[输入格式]
输入文件的第一行包含三个用空格隔开的整数:N,P 和K。
第二行到第P+1 行:每行分别都为空格隔开的整数:Ai,Bi 和Li。
[输出格式]
输出文件中仅包含一个整数,表示在这项工程上的最小支出。如果任务不可能完成,则输出-1。
[输入样例]
5 7 1
1 2 5
3 1 4
2 4 8
3 2 3
5 2 9
3 4 7
4 5 6
[输出样例]
4
***想到最短路径但是发现后面的不会做了
1 #include <cstdio> 2 #include <string> 3 #include <cstring> 4 #include <algorithm> 5 using std::sort; 6 long mid; //二分中点值 7 bool used[1010]; 8 long map0[1010][1010]; //某点到某点的距离 9 long map[1010][1010]; 10 long dist[1010]; 11 long c[3010000]; //所有距离从小到大的排序 12 long que[2000010]; 13 long n, k; 14 const long qmod = 2000000; 15 long getint() //这是个输入的分函数 16 { 17 long rs=0;bool sgn=1;char tmp; 18 do tmp = getchar(); 19 while (!isdigit(tmp)&&tmp-‘-‘); 20 if (tmp == ‘-‘){tmp=getchar();sgn=0;} 21 do rs=(rs<<3)+(rs<<1)+tmp-‘0‘; 22 while (isdigit(tmp=getchar())); 23 return sgn?rs:-rs; 24 } 25 void spfa() //spfa求最短路径 26 { 27 memset(dist,0x3f,sizeof dist); //初始化dis[]为无穷大 28 long l = 0; 29 long r = 0; 30 r ++; 31 que[r] = 1; 32 dist[1] = 0; 33 while (l < r) 34 { 35 l ++; 36 if (l == qmod) 37 l = 0; 38 long u = que[l]; 39 used[u] = false; 40 for (long v=1;v<n+1;v++) 41 { 42 if (map0[u][v]<0x3f3f3f3f && dist[v]>dist[u]+map[u][v]) 43 { 44 dist[v] = dist[u] + map[u][v]; 45 if (!used[v]) 46 { 47 used[v] = true; 48 r ++; 49 if (r == qmod) 50 r = 0; 51 que[r] = v; 52 } 53 } 54 } 55 } 56 } 57 bool can() 58 { 59 for (long i=1;i<n+1;i++) 60 { 61 for (long j=i;j<n+1;j++) 62 { 63 if (map0[i][j] == 0x3f3f3f3f) 64 map[i][j] = 0x3f3f3f3f; 65 else if (map0[i][j] <= mid) 66 map[i][j] = map[j][i] = 0; 67 else 68 map[i][j] = map[j][i] = 1; 69 } 70 } 71 spfa(); 72 if (dist[n] > k) 73 return false; 74 else 75 return true; 76 } 77 bool check() 78 { 79 for (long i=1;i<n+1;i++) 80 for (long j=i;j<n+1;j++) 81 map[i][j] = map[j][i] = 1; // 每条路都先赋值为 1 82 spfa(); 83 return dist[n] < 0x3f3f3f3f; 84 } 85 int main() 86 { 87 // freopen("phone.in","r",stdin); 88 // freopen("phone.out","w",stdout); 89 n = getint(); 90 long p = getint(); 91 k = getint(); //输入n,p,k; 92 memset(map0,0x3f,sizeof map0); //初始化map[][] 全为0 ; 93 for (long i=1;i<p+1;i++) 94 { 95 long a = getint(); 96 long b = getint(); 97 long cc = getint(); //输入起点和终点还有他们间距离 98 map0[a][b] = map0[b][a] = cc; 99 c[++c[0]] = cc; //将某两点之间的距离储存下来 100 } 101 sort(c+1,c+1+c[0]);//进行排序(从小到大) 102 long tmp = 1; 103 for (long i=2;i<c[0]+1;i++) 104 if (c[i]!=c[tmp]) 105 c[++tmp] = c[i]; //把距离大小相等的合并起来 106 c[0] = 0; 107 long l = 0; 108 long r = tmp; 109 long ans = 0x3f3f3f3f; //先把答案初始化为无穷大 110 if (!check()) 111 { 112 printf("-1"); 113 return 0; 114 } 115 while (l <= r) 116 { 117 long mm = (l+r)>>1; 118 mid = c[mm]; 119 if (can()) 120 { 121 if (ans > mid) 122 ans = mid; 123 r = mm-1; 124 } 125 else 126 { 127 l = mm+1; 128 } 129 } 130 printf("%ld",ans); 131 return 0; 132 }
****把原图中距离大于x的电话线对应的边赋值为1,小于等于x的边赋值为0,变成一个01图,求最短路径,二分出答案
原文地址:https://www.cnblogs.com/rax-/p/9057422.html