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

题目OJ地址:http://cdqz.openjudge.cn/noip/1011/

 

摘要:

时间限制: 
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。
 
  请你计算一下,将电话线引到震中市最少需要在电话线上花多少钱?
 
【输入】
 
输入文件的第一行包含三个数字n,P,k;
第二行到第p+1行,每行分别都为三个整数al,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
 
 
  本题应该说还是不难,只是很难写。话说我写了三节晚自习,终于调通了。这也是我第一次写SPFA,之前以为多长的,后来发现其实很短十几行就可以解决。
  关于SPFA,参考:http://www.nocow.cn/index.php/SPFA
 
 
  本题的做法是:先SPFA找到起点到终点的最短边数,判断它是否小于k,如果小于就直接输出0,否则开始下面的计算。
 
 
  我们知道事实上费用为本条路径上第k+1大的边的权。也就是说,如果费用为P,那么路径上一定经过k条权值大于P的边。设s[i]表示到i号节点所需经过的大于P的边的数量的最小值,则可以证明s[i]关于P是单调递减的,故思路就很明显了——二分答案。
 
 
  二分P,每次SPFA找出到n点所需经过大于P的边的数量的最小值(具体方法和最短路差不多,可以参考代码),然后与k进行比较:如果s[n]>k,说明必须经过大于k条边权大于P的边,即总费用高于P,将P提升;如果s[n]<=k,说明有可能经过小于k条边权小于P的边,即总费用可能小于等于P,将P下调。
 
 
  应该注意的是之前要先DFS或BFS一遍看看n是否能达到,如果不能直接输出-1。
 
  参考我的代码:
View Code
  1 #include<iostream>
  2 #include<queue>
  3 #include<vector>
  4 #include<fstream>
  5 #include<set>
  6 
  7 using namespace std;
  8 
  9 struct node
 10 {
 11     int val,end;
 12 };
 13 
 14 ifstream fin("phone.in");
 15 ofstream fout("phone.out");
 16 
 17 #define INF 0x7fffffff
 18 
 19 vector<node> graph[2001];
 20 set<int> se;
 21 int val[2001],qual[2001],n,m,whcissb,k,K,mark[2001];
 22 
 23 inline int min(int a,int b)
 24 {
 25     return a<b?a:b;
 26 }
 27 
 28 bool bfs()
 29 {
 30     queue<int> q;
 31     while(!q.empty()) q.pop();
 32     q.push(1);mark[1]=1;
 33     while(!q.empty())
 34     {
 35         int t=q.front();
 36         q.pop();
 37 
 38         for(int i=0;i<graph[t].size();i++)
 39         {
 40             if(mark[graph[t][i].end]==0) q.push(graph[t][i].end);
 41             mark[graph[t][i].end]=1;
 42         }
 43     }
 44 
 45     return mark[n]==1;
 46 }
 47 
 48 void find(int p)
 49 {
 50     queue<int> q;
 51     while(!q.empty()) q.pop();
 52     q.push(1);
 53     for(int i=1;i<=n;i++)
 54         val[i]=INF;
 55     val[1]=0;
 56 
 57     while(!q.empty())
 58     {
 59         int t=q.front();
 60         q.pop();
 61 
 62         for(int i=0;i<graph[t].size();i++)
 63             if(val[t]+1<val[graph[t][i].end])
 64             {
 65                 val[graph[t][i].end]=val[t]+1;
 66                 q.push(graph[t][i].end);
 67             }
 68     }
 69 }
 70 
 71 void find2(int p)
 72 {
 73     queue<int> q;
 74     while(!q.empty()) q.pop();
 75     q.push(1);
 76     for(int i=1;i<=n;i++)
 77         val[i]=INF,qual[i]=INF;
 78     val[1]=0;qual[1]=0;
 79 
 80     while(!q.empty())
 81     {
 82         int t=q.front();
 83         q.pop();
 84 
 85         for(int i=0;i<graph[t].size();i++)
 86             if(graph[t][i].val>p)
 87             {
 88                 if(qual[t]+1<qual[graph[t][i].end])
 89                 {
 90                     qual[graph[t][i].end]=qual[t]+1;
 91                     q.push(graph[t][i].end);
 92                 }
 93             }
 94             else
 95             {
 96                 if(qual[t]<qual[graph[t][i].end])
 97                 {
 98                     qual[graph[t][i].end]=qual[t];
 99                     q.push(graph[t][i].end);
100                 }
101             }
102     }
103 }
104 
105 void solve()
106 {
107     int s=1,t=whcissb;
108     while(t-s>1)
109     {
110         int mid=(s+t)>>1;
111         find2(mid);
112         if(qual[n]<=k) t=mid;
113         else s=mid+1;
114     }
115     find2(s);
116     if(qual[n]<=k) fout<<s<<endl;
117     else fout<<t<<endl;
118 }
119 
120 int main()
121 {
122     fin>>n>>m>>k;
123 
124     for(int i=1;i<=m;i++)
125     {
126         node p;int s,e,v;
127         fin>>s>>e>>v;
128         p.end=e;
129         p.val=v;
130         graph[s].push_back(p);
131         p.end=s;
132         graph[e].push_back(p);
133 
134         if(v>whcissb) whcissb=v;
135     }
136 
137     if(!bfs()) 
138     {
139         fout<<-1<<endl;
140         return 0;
141     }
142 
143     find(INF);
144     K=val[n];
145     if(K<k) fout<<0<<endl;
146     else solve();
147 
148     return 0;
149 }

 

 
posted on 2012-05-26 09:32  stickjitb  阅读(212)  评论(0)    收藏  举报