csu 1307 最大值最小,
来源:互联网 发布:ubuntu有什么用 编辑:程序博客网 时间:2024/05/16 23:42
Submit: 550 Solved: 125
[Submit][Status][Web Board]
Description
Alice想要从城市A出发到城市B,由于Alice最近比较穷(不像集训队陈兴老师是个rich second),所以只能选择做火车从A到B。不过Alice很讨厌坐火车,火车上人比较多,比较拥挤,所以Alice有很严格的要求:火车的相邻两站间的最大距离尽可能的短,这样Alice就可以在停站的时候下车休息一下。当然Alice希望整个旅途比较短。
Input
有多组测试数据。
每组测试数据的第一行有两个整数N,M,A,B(N<=2000, M<=50000, N >=2, A,B<=N),其中N是城市的个数,M是城市间通火车的个数。
A,B是Alice起始的城市与目的地城市,城市的标号从1开始。
接下来的M行每行三个整数u,v,w表示从u到v和从v到u有一条铁路,距离为w, u,v<=N, w<=10000。
Output
对于每组测试数据输出满足Alice要求的从A到B的最短距离。
Sample Input
3 3 1 21 2 801 3 402 3 503 3 1 21 2 901 3 102 3 204 5 1 41 2 81 4 91 3 102 4 73 4 8
Sample Output
903015
初看没思路,细看还是没思路,想想能不能用最小生成树做,后来发现如果从起点到几个点有相同的距离的话,用prime也不好算。其实题目的意思可以转化成:去掉较长的边,看能否通过其他较之短的边而达到。譬如从A到B有多条路,一条是直达的路,DA-B=35,一条是先到C,DA-C15,然后由C到B,距离是30.所以按题意应该是先到C,再到B。此时,如果有C到F,DC-F=20,然后由F到B,DF-B=25,那么他应该走这样的路线:A---C---F---B;
所以可以这么考虑:设边的最大长度为DMAX,然后,逐渐减小DMAX的长度,如果减小后用SPFA依旧能算出距离D!=无穷大,说明该减小的操作是正确的,然后再减小。。。但如果用SPFA算出距离D为无穷大,说明减小到该极限长度后,出发点和目的地无法到达。此时就应该扩大DMAX的长度.
如果用暴力的话,会超时,所以得用二分了,二分最大边和最小边。
如果是最小值最大的话,应该也是这种上路,逐渐真大Dmin,然后balabala.
#include <iostream>#include <cstdio>#include <cstring>#include <queue>#include <algorithm>using namespace std;const int maxm=100000;const int inf=0x3f3f3f3f;int next[maxm],inq[maxm],first[maxm],v[maxm],w[maxm],d[maxm],dis[maxm];int n,a1,b1,m,i,s,ed,w1,tmp;int e;int l,r,mid;int cmp(int x,int y){ return x>y;}void init(){ e=0; memset(first,-1,sizeof(first));}void add_edge(int a,int b,int c){ w[e]=c;v[e]=b;next[e]=first[a];first[a]=e++;}int spfa(int x,int y){ queue<int >q; memset(d,0x3f,sizeof(d)); d[x]=0;inq[x]=1; q.push(x); while(!q.empty()) { int u=q.front(); q.pop(); inq[u]=0; for(i=first[u];i!=-1;i=next[i]) if(w[i]<=mid) { if(d[v[i]]>d[u]+w[i]) { d[v[i]]=d[u]+w[i]; if(!inq[v[i]]) q.push(v[i]),inq[v[i]]=1; } } }return d[y];}//* 用二分的思想去递减int main(){ int ans1,ans2,ans; while(cin>>n>>m>>a1>>b1) { memset(inq,0,sizeof(inq)); init(); l=1<<30; r=-1; for(i=1;i<=m;i++) { scanf("%d%d%d",&s,&ed,&w1); add_edge(s,ed,w1); add_edge(ed,s,w1); l=min(l,w1);//选出最小的边 r=max(r,w1);//选出最大的边 } //l=1<<30;r=-1; mid=(l+r)>>1;//用二分的关键思路在于:把一些长的边“舍去”,看看能否通过较短的几条边到达。//如果能,说明该边的却可以舍去,如果不能,说明应该扩大边的最大长度,//即在二分的时候,选择右半边。 while(l<=r) { tmp=spfa(a1,b1); //cout<<"tmp"<<tmp<<endl; if(tmp==0x3f3f3f3f) l=mid+1; else r=mid-1,ans=tmp; mid=(l+r)>>1; } cout<<ans<<endl; }}/*用暴力看看能不能实现,结果会超时int main(){ int ans1,ans2,ans,j; while(cin>>n>>m>>a1>>b1) { memset(inq,0,sizeof(inq)); init(); for(i=1;i<=m;i++) { scanf("%d%d%d",&s,&ed,&w1); add_edge(s,ed,w1); add_edge(ed,s,w1); dis[i]=w1; } sort(dis+1,dis+m+1,cmp); for(j=1;j<=m;j++) { //cout<<"dis"<<j<<"="<<dis[j]<<endl; mid=dis[j]; tmp=spfa(a1,b1); //cout<<tmp<<endl; if(tmp==inf) { mid=dis[j-1]; tmp=spfa(a1,b1); break; } } cout<<tmp<<endl;}return 0;}*/
0 0
- csu 1307 最大值最小,
- 最小最大值
- CSU 1216 异或最大值
- csu-1216: 异或最大值
- CSU 1216 —— 异或最大值
- CSU 1216 异或最大值【字典树】
- CSU 1216 异或最大值 01trie
- CSU 1216 异或最大值(01Trie)
- 最大值最小问题
- 最小与最大值
- 运算符求最小最大值
- js 获取数组最小/最大值
- CSU-1216: 异或最大值-trie-01字典树
- CSU 1216: 异或最大值(字典树+贪心)
- CSU 1869 中南大学网络赛C题 树上最大值
- CSU
- CSU
- CSU
- php uploadify上传
- #include<>与#include“”
- 关于虚表
- php中上传图片文件,并且以上传时的时间戳命名文件,并将文件的路径存在session中以便使用。
- Android里webviewActivity一般功能实现
- csu 1307 最大值最小,
- Quartz学习
- Session丢失的解决办法小结
- 嵌入式工程师的硬件和软件道路选择
- ARM GCC 内嵌(inline)汇编手册
- Java学习笔记<5>数组
- struts2和json的整合
- INADDRANY
- 《炒股的智慧》读后感