• Rinne Loves Dynamic Graph(牛客算法周周练16)


    Rinne Loves Dynamic Graph(牛客算法周周练16)

    Problem:

    Rinne 学到了一个新的奇妙的东西叫做动态图,这里的动态图的定义是边权可以随着操作而变动的图。
    当我们在这个图上经过一条边的时候,这个图上所有边的边权都会发生变动。

    定义变动函数 (f(x) = frac{1}{1-x}),表示我们在图上走过一条边后,图的边权变动情况。

    这里指的“图的变动”的意思是将每条边的边权代入上函数,得到的值即为该次变动后的边权。

    现在 Rinne 想要知道,在这个变动的图上从 1 到 n 的最短路径。
    因为 Rinne 不喜欢负数,所以她只需要你输出经过的边权权值绝对值之和最小的那个值就可以了。
    输出答案保留三位小数。

    Input:

    第一行两个正整数 N,M,表示这个动态图的点数和边数。
    接下来 M 行,每行三个正整数 u,v,w,表示存在一条连接点 u,v 的无向边,且初始权值为 w。

    Output:

    如果能到达的话,输出边权绝对值之和最小的答案,保留三位小数。
    否则请输出 -1。

    Example:

    Input:

    3 3
    1 2 2
    2 3 2
    3 1 3
    

    Output:

    3.000
    

    Note:

    (1 o 2 o 3),总花费 (2 + |frac{1}{1-2}| = 3)

    Remark:

    n≤100000,m≤300000,2≤x≤1000

    题解:

    最短路DP,分析边权的变化公式可知:

    [f(x)=frac{1}{1-x}\f(f(x))=1-frac{1}{x}\f(f(f(x)))=x ]

    所以,对于边权的值根据已走过的边数存在三种情况:

    [edge mod 3==1 o frac{1}{1-x}\edge mod 3==2 o 1-frac{1}{x}\edge mod 3==0 o x ]

    Dijkstra计算最短路,记录走过边数,计算边权代入计算最小值。

    Code:

    /**********************************************************
    * @Author: 			   Kirito
    * @Date:   			   2020-06-24 21:11:15
    * @Last Modified by:   Kirito
    * @Last Modified time: 2020-07-23 15:36:56
    * @Remark: 
    **********************************************************/
    #include <bits/stdc++.h>
    #define lowbit(x) (x&(-x))
    #define CSE(x,y) memset(x,y,sizeof(x))
    #define INF 0x3f3f3f3f
    #define Abs(x) (x>=0?x:(-x))
    #define FAST ios::sync_with_stdio(false);cin.tie(0);
    using namespace std;
    
    typedef long long ll;
    typedef pair<int,int> pii;
    typedef pair<ll , ll> pll;
    
    struct node
    {
    	int id,x;
    	double dis;
    	bool operator < (const node &b) const{
    		return dis>b.dis;
    	}
    };
    
    const int maxn=611111;
    //graph
    int first[maxn],nxt[maxn],u[maxn],v[maxn],w[maxn];
    int n,m,cnt;
    //dij
    double dis[maxn][5];
    int book[maxn][5];
    //link-form
    void add(int x,int y,int d)
    {
    	cnt++;
    	u[cnt]=x;v[cnt]=y;w[cnt]=d;
    	nxt[cnt]=first[u[cnt]];first[u[cnt]]=cnt;
    	return;
    }
    //INi
    void ini()
    {
    	for(int i=0;i<=n;i++){
    		dis[i][0]=dis[i][1]=dis[i][2]=1e30;
    	}
    	return;
    }
    //getdis
    double getdis(int nm,int w)
    {
    	switch(nm)
    	{
    		case 0: return fabs(1.0*w);
    		case 1: return fabs(1.0/(1.0-w));
    		case 2: return fabs(1.0-1.0/w);
    	}
    	return fabs(1.0*w);
    }
    //Dijkstra
    void dijkstra()
    {
    	ini();CSE(book,0);
    	priority_queue<node> box;
    	box.push(node{0,1,0});dis[1][0]=0;
    	while(!box.empty())
    	{
    		int x=box.top().x,t=box.top().id;;box.pop();
    		if(book[x][t]) continue;
    		book[x][t]=1;
    		for(int i=first[x];i!=-1;i=nxt[i]){
    			int y=v[i];
    			int t2=(t+1)%3;
    			double d=getdis(t,w[i])+dis[x][t];
    			if(book[y][t2]) continue;
    			if(dis[y][t2]>d){
    				dis[y][t2]=d;
    				box.push(node{t2,y,dis[y][t2]});
    			}
    		}
    	}
    	return;
    }
    
    
    int main()
    {
    	#ifndef ONLINE_JUDGE
    	freopen("in.in","r",stdin);
    	#endif
    	CSE(first,-1);CSE(nxt,-1);cnt=0;
    	scanf("%d%d",&n,&m);
    	for(int i=0;i<m;i++){
    		int x,y,z;
    		scanf("%d%d%d",&x,&y,&z);
    		add(x,y,z);
    		add(y,x,z);
    	}
    	dijkstra();
    	double ans=min(dis[n][0],min(dis[n][1],dis[n][2]));
    	int k=(book[n][0]|book[n][1]|book[n][2]);
    	if(k)
    		printf("%.3lf
    ",ans);
    	else
    		printf("-1
    ");
    	return 0;
    }
    
  • 相关阅读:
    【转】当你输入一个网址的时候,实际会发生什么?
    opencv 操作本地摄像头实现录像
    谷歌笔试题——排序,只允许0和其他元素交换
    判断素数的相关代码
    VS2010 代码自动对齐 快捷键
    谷歌的一道面试题
    各种排序算法代码汇总
    冒泡排序
    lua环境变量
    lua迭代
  • 原文地址:https://www.cnblogs.com/LeafLove/p/13367213.html
Copyright © 2020-2023  润新知