zoukankan      html  css  js  c++  java
  • 【JZOJ5771】遨游【二分】【DFS】

    题目大意:

    题目链接:https://jzoj.net/senior/#main/show/5771
    题目图片:
    https://www.z4a.net/images/2018/09/22/Screenshot949650fe938ea13c.png
    https://www.z4a.net/images/2018/09/22/Screenshot-11765113419a5a9a4.md.png
    https://www.z4a.net/images/2018/09/22/2.md.png
    https://www.z4a.net/images/2018/09/22/1.md.png
    给出nn个省,每个神有自己的折扣per[i]per[i],每个省有num[i]num[i]个城市。有mm条路,每条路连接两个城市u[i]u[i]v[i]v[i],原价是w[i]w[i],但打折后的价格就是(per[u[i](per[u[i]所在城市]+per[v[i]]+per[v[i]所在城市])×0.5])\times 0.5
    如果要从sstt的路程免费,那么就得有打折后价格在[L,R][L,R]区间之间的路免费通行。求在LL最大的情况下且RR尽量小的L,RL,R


    思路:

    可以二分LLRR
    二分嵌套二分,第一重二分LL,第二重二分RR
    每次二分完LL之后,搜索一遍能否只走价格大于LL的路到达终点,如果可以,就二分RR
    每次二分RR之后,如果搜到可以只走价格大于LL且小于RR的路线的话,那么久将这一组答案记录下来。
    最终输出记录的答案即可。


    代码:

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #define N 101000
    using namespace std;
    
    int n,m,num,s,t,l1,r1,l2,r2,mid1,mid2,tot,L,R;
    int u[N],v[N],pos[N],head[N];
    double w[N],per[N];
    bool ok,vis[N];
    
    struct edge
    {
    	int dis,to,next;
    }e[N*2];
    
    void add(int from,int to,double dis)
    {
    	e[++tot].to=to;
    	e[tot].dis=dis;
    	e[tot].next=head[from];
    	head[from]=tot;
    }
    
    bool dfs(int x,int l,int r)  //搜索是否有方法可以在限制条件下到达t
    {
    	if (x==t) return true;
    	if (vis[x]) return false;
    	vis[x]=1;
    	for (int i=head[x];~i;i=e[i].next)
    	 if (e[i].dis>=(double)l&&e[i].dis<(double)r)
    	  if (dfs(e[i].to,l,r)) return true;
    	return false;
    }
    
    int main()
    {
    	memset(head,-1,sizeof(head));
    	scanf("%d%d",&n,&m);
    	for (int i=1;i<=m;i++)
    	 scanf("%d%d%lf",&u[i],&v[i],&w[i]);
    	for (int i=1;i<=n;i++)
    	{
    		scanf("%d",&num);
    		int x;
    		for (int j=1;j<=num;j++)
    		{
    			scanf("%d",&x);
    			pos[x]=i;
    		}
    	}
    	for (int i=1;i<=n;i++)
    	 scanf("%lf",&per[i]);
    	for (int i=1;i<=m;i++)
    	{
    	   add(u[i],v[i],(per[pos[u[i]]]+per[pos[v[i]]])/2.0*w[i]*0.01);
    	   add(v[i],u[i],(per[pos[u[i]]]+per[pos[v[i]]])/2.0*w[i]*0.01);
    	}
    	scanf("%d%d",&s,&t);
    	l1=0;
    	r1=15000;
    	while (l1<=r1)  //二分L
    	{
    		mid1=(l1+r1)/2;
    		l2=mid1;
    		r2=15000;
    		ok=false;
    		memset(vis,0,sizeof(vis));
    		if (dfs(s,mid1,1e9))
    		 while (l2<=r2)  //二分R
    		 {
    			mid2=(l2+r2)/2;
    			memset(vis,0,sizeof(vis));
    			if (dfs(s,mid1,mid2))
    			{
    				ok=true;
    				L=mid1;
    				R=mid2;
    				r2=mid2-1;
    			}
    			else l2=mid2+1;
    		 }
    		if (ok) l1=mid1+1;
    		 else r1=mid1-1;
    	}
    	printf("%d %d\n",L,R);
    	return 0;
    }
    
  • 相关阅读:
    sh_04_第1个函数改造
    sh_03_第1个函数
    sh_02_快速体验
    sh_01_九九乘法表
    11_测试模块
    sh_12_转义字符
    sh_11_九九乘法表
    sh_10_嵌套打印小星星
    Mariadb/Redis数据库
    部署django项目
  • 原文地址:https://www.cnblogs.com/hello-tomorrow/p/11998569.html
Copyright © 2011-2022 走看看