洛谷 P1396 营救
2016-11-16 07:47
176 查看
题目描述
“咚咚咚……”“查水表!”原来是查水表来了,现在哪里找这么热心上门的查表员啊!小明感动的热泪盈眶,开起了门…… 妈妈下班回家,街坊邻居说小明被一群陌生人强行押上了警车!妈妈丰富的经验告诉她小明被带到了t区,而自己在s区。 该市有m条大道连接n个区,一条大道将两个区相连接,每个大道有一个拥挤度。小明的妈妈虽然很着急,但是不愿意拥挤的人潮冲乱了她优雅的步伐。所以请你帮她规划一条从s至t的路线,使得经过道路的拥挤度最大值最小。
输入输出格式
输入格式: 第一行四个数字n,m,s,t。 接下来m行,每行三个数字,分别表示两个区和拥挤度。 (有可能两个区之间有多条大道相连。) 输出格式: 输出题目要求的拥挤度。
输入输出样例
输入样例#1: 3 3 1 3 1 2 2 2 3 1 1 3 3 输出样例#1: 2
说明
数据范围 30% n<=10 60% n<=100 100% n<=10000,m<=2n,拥挤度<=10000 题目保证1<=s,t<=n且s<>t,保证可以从s区出发到t区。
样例解释:
小明的妈妈要从1号点去3号点,最优路线为1->2->3。
思路:
一道模板题咋都能做 一是可以二分拥挤度跑spfa 二是可以找最小生成树 有一个定理 但是不会证 定理:MST中的最长边必定小于其他生成树中的最长边. 那么可以在最小生成树中找最长边 三是可以找最小生成树 再LCA求 不过我写的有点问题 最后一个点爆内存 只有90分
代码:
// 二分ans //spfa检验 #include<cstdio> #include<iostream> #define MAXN 10010 #define INF 100000000 using namespace std; int dis[MAXN],n,m,s,t,l,r,q[MAXN*10],ans; struct node{ int to; int next; int val; }; node e[MAXN*4]; int head[MAXN*4],tot; bool vis[MAXN]; inline void read(int&x) { int f=1;x=0;char c=getchar(); while(c>'9'||c<'0') {if(c=='-') f=-1;c=getchar();} while(c>='0'&&c<='9') x=10*x+c-48,c=getchar(); x=x*f; } inline void add(int x,int y,int z) { e[++tot].to=y; e[tot].val=z; e[tot].next=head[x]; head[x]=tot; } inline bool inc(int&x) { return x=x+1==n?0:x+1; } inline bool spfa(int x,int w) { for(int i=1;i<=n;i++) dis[i]=INF,vis[i]=false; int h=0,ta=0,head1=1,tail=1;q[head1]=s;dis[s]=0; while(head1<=tail) { int u=q[head1++];vis[u]=false; for(int i=head[u];i;i=e[i].next) { int v=e[i].to; if(dis[v]>dis[u]+e[i].val&&e[i].val<=w) { dis[v]=dis[u]+e[i].val; if(!vis[v]) { q[++tail]=v; vis[v]=true; } } } } if(dis[t]==INF) return false; else return true; } int main() { int x,y,z; read(n);read(m);read(s);read(t); for(int i=1;i<=m;i++) { read(x);read(y);read(z); add(x,y,z);add(y,x,z); r=max(r,z); } while(l<=r) { int mid=(l+r)>>1; if(spfa(s,mid)) ans=mid,r=mid-1; else l=mid+1; } printf("%d\n",ans); return 0; }
//最小生成树+LCA 只有90(T_T) #include<cstdio> #include<iostream> #include<algorithm> #define MAXN 10001 using namespace std; struct node { int x,y; int w; bool operator < (const node b) const{ return w<b.w; } }; struct data { int to; int next; int val; }; node a[MAXN*2]; data e[MAXN]; int n,m,s,t,fa[MAXN]; int head[MAXN],tot; int f[MAXN],deep[MAXN],dis[MAXN]; inline void read(int&x) { int f=1;x=0;char c=getchar(); while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();} while(c>='0'&&c<='9') x=x*10+c-48,c=getchar(); x=x*f; } inline int find(int x) { if(x==fa[x]) return x; fa[x]=find(fa[x]); return fa[x]; } inline void add(int x,int y,int z) { e[++tot].to=y; e[tot].val=z; e[tot].next=head[x]; head[x]=tot; } inline void dfs(int now,int from,int dep,int v) { f[now]=from; deep[now]=dep; dis[now]=v; for(int i=head[now];i;i=e[i].next) { int v=e[i].to; if(v!=from) dfs(v,now,dep+1,e[i].val); } } inline void kurskal() { for(int i=1;i<=n;i++) fa[i]=i; int cnt=0; for(int i=1;i<=m;i++) { int f1=find(a[i].x); int f2=find(a[i].y); if(f1!=f2) { fa[f1]=f2; cnt++; add(a[i].x,a[i].y,a[i].w); add(a[i].y,a[i].x,a[i].w); } if(cnt==n-1) break; } return; } inline int lca(int a,int b) { int ans=0; while(deep[a]>deep[b]) ans=max(ans,dis[a]),a=f[a]; while(deep[a]<deep[b]) ans=max(ans,dis[b]),b=f[b]; if(a==b) return ans; while(a!=b) { ans=max(ans,dis[a]); ans=max(ans,dis[b]); a=f[a];b=f[b]; } return ans; } int main() { read(n);read(m);read(s);read(t); for(int i=1;i<=m;i++) read(a[i].x),read(a[i].y),read(a[i].w); sort(a+1,a+1+m); kurskal(); dfs(1,-1,0,0); int LCA=lca(s,t); printf("%d\n",LCA); return 0; }
相关文章推荐
- 营救(洛谷 P1396)
- 洛谷[P1396]营救 并查集
- 洛谷 P1396 营救
- 洛谷 P1396 营救
- |洛谷|图论生成树|P1396 营救
- P1396 营救 洛谷
- 洛谷 P1396 营救
- P1396 营救
- 洛谷 P1396
- 洛谷 1396 营救
- P1396 营救
- [P1396]营救
- 洛谷 P4011 孤岛营救问题【bfs】
- [LUOGU] P1396 营救
- P1396 营救
- P2910 [USACO08OPEN]寻宝之路Clear And Present Danger 洛谷
- 洛谷 P1083 借教室【二分+差分/线段树】
- 洛谷 P1424 小鱼的航程(改进版)
- 线段树 洛谷P3932 浮游大陆的68号岛
- 洛谷 P3371 【模板】单源最短路径