电话网络

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