【牛客 - 370H】Rinne Loves Dynamic Graph(分层图最短路)
題干:
鏈接:https://ac.nowcoder.com/acm/contest/370/H
來源:牛客網
?
Rinne 學到了一個新的奇妙的東西叫做動態圖,這里的動態圖的定義是邊權可以隨著操作而變動的圖。
當我們在這個圖上經過一條邊的時候,這個圖上所有邊的邊權都會發生變動。
定義變動函數 f(x)=11?xf(x)=11?x,表示我們在圖上走過一條邊后,圖的邊權變動情況。
這里指的“圖的變動”的意思是將每條邊的邊權代入上函數,得到的值即為該次變動后的邊權。
現在 Rinne 想要知道,在這個變動的圖上從 1 到 n 的最短路徑。
因為 Rinne 不喜歡負數,所以她只需要你輸出經過的邊權權值絕對值之和最小的那個值就可以了。
輸出答案保留三位小數。
輸入描述:
第一行兩個正整數 N,M,表示這個動態圖的點數和邊數。 接下來 M 行,每行三個正整數 u,v,w,表示存在一條連接點 u,v 的無向邊,且初始權值為 w。輸出描述:
如果能到達的話,輸出邊權絕對值之和最小的答案,保留三位小數。 否則請輸出 -1。示例1
輸入
復制
3 3 1 2 2 2 3 2 3 1 3輸出
復制
3.000說明
走?1→2→31→2→3,總花費?2+|11?2|=32+|11?2|=3備注:
n≤100000,m≤300000,2≤x≤1000解題報告:
? ?mmp的這題卡常卡我半天,,不能用spfa不能用vector、、、還有就是注意數組大小,邊數要開6*MAXM,,因為是雙向邊、、不然就會TLE。
? ?讀題發現這個函數是個迭代函數。
? 發現這一點之后這題就解決一大半了,建三層的圖,每一層只能連向更高層。跑Dijkstra就行了。最后在三個答案中取最小。當然這題也可以用dp的思想去做。
? 注意這題有個坑,就是你加邊的時候不能直接更新了w,就將w取絕對值了,而是應該,傳參的時候傳進去絕對值,但是w還是保持本身的值。(這個坑不注意還真發現不了、、、就看你寫的姿勢如何了)
AC代碼:
#include<cstdio> #include<iostream> #include<algorithm> #include<queue> #include<map> #include<vector> #include<set> #include<string> #include<cmath> #include<cstring> #define ll long long #define fi first #define se second #define pb push_back #define pm make_pair using namespace std; const int MAX = 2e5 + 5; typedef pair<int,double> PID; typedef pair<double,int> PDI; const double INF = 99999999999; int n,m; //vector<PID > vv[3*MAX]; double dis[MAX*3]; bool vis[MAX*3]; int head[MAX*3]; struct Node {int to,ne;double w; } e[MAX*15]; int tot; void add(int u,int v,double w) {e[++tot].to = v;e[tot].w = w;e[tot].ne = head[u];head[u] = tot; } void Dijkstra() {for(int i = 1; i<=3*n; i++) dis[i] = INF;dis[1] = 0;priority_queue<PDI> pq;pq.push(pm(0,1));while(!pq.empty()) {PDI cur = pq.top();pq.pop();if(vis[cur.se]) continue;vis[cur.se] = 1;for(int i = head[cur.se]; i!=-1; i=e[i].ne) {int v = e[i].to;if(dis[cur.se] + e[i].w < dis[v]) {dis[v] = dis[cur.se] + e[i].w;pq.push(pm(-dis[v],v));}}} } int main() {memset(head,-1,sizeof head);cin>>n>>m;int u,v;double w;for(int i = 1; i<=m; i++) {scanf("%d%d%lf",&u,&v,&w);//w = fabs(w);add(u,v+n,fabs(w));add(v,u+n,fabs(w));w = (1.0/(1-w));add(u+n,v+2*n,fabs(w));add(v+n,u+2*n,fabs(w));w = (1.0/(1-w));add(u+2*n,v,fabs(w));add(v+2*n,u,fabs(w));}Dijkstra();double ans = INF;for(int i = 0; i<=2; i++) {ans = min(ans,dis[n+i*n]);}if(ans > 9999999999) printf("-1\n");else printf("%.3lf\n",ans);return 0 ;}AC代碼2:(dp思路)
#include<bits/stdc++.h> using namespace std; const int MOD=1e9+7; const int MAX=5e5+10; typedef long long ll; struct lenka {int x,y;double cost;bool operator<(const lenka&q)const{return q.cost<cost;} }; vector<pair<int,int> >e[MAX]; priority_queue<lenka>p; double d[MAX][3]; double f(int x,int tp) {if(tp==0)return x*1.0;if(tp==1)return 1/(x-1.0);return 1-1.0/x; } void bfs() {p.push((lenka){1,0,0.0});d[1][0]=0;while(!p.empty()){lenka now=p.top();p.pop();if(fabs(d[now.x][now.y]-now.cost)>1e-8)continue;for(int i=0;i<e[now.x].size();i++){pair<int,int>nex=e[now.x][i];if(d[nex.first][(now.y+1)%3]>now.cost+f(nex.second,now.y)){d[nex.first][(now.y+1)%3]=now.cost+f(nex.second,now.y);p.push((lenka){nex.first,(now.y+1)%3,d[nex.first][(now.y+1)%3]});}}} } int main() {int n,m;cin>>n>>m;for(int i=1;i<=n;i++)d[i][0]=d[i][1]=d[i][2]=6e18;while(m--){int x,y,z;scanf("%d%d%d",&x,&y,&z);e[x].push_back({y,z});e[y].push_back({x,z});}bfs();double ans=*min_element(d[n],d[n]+3);if(ans>5e18)puts("-1");else printf("%.3lf\n",ans);return 0; }再來一個:
#pragma comment(linker, "/STACK:102400000,102400000")//防止棧溢出!!! #include<cstdio> #include<iostream> #include<stdlib.h> #include<malloc.h> #include<cstring> #include<algorithm> #include<math.h> #include <set> #include <vector> #include <map> #include <queue> #include <stack> #include<time.h> #include<ctype.h> #define REP(I,N) for (I=0;I<N;I++) #define rREP(I,N) for (I=N-1;I>=0;I--) #define rep(I,S,N) for (I=S;I<N;I++) #define rrep(I,S,N) for (I=N-1;I>=S;I--) #define For(i,x,y) for(long long i=(long long)(x);i<(long long)(y);++i) #define rFOR(I,S,N) for(long long I=N;I>=S;I--) #define SWAP(x,y) {(x) = (x)^(y); (y)=(x)^(y); (x)=(x)^(y);} #define D(x) cerr<<#x<<" = "<<x<<endl #define ms(a,b) memset(a,b,sizeof(a)) #define lowbit(x) ((x)&(-x)) using namespace std; typedef long long ll; typedef unsigned long long ull; const double eps=1e-6; const int MOD = 1e9+6 ; const int mod = 1e9+7; const int INF = 0x3f3f3f3f; const int MAXN =100010;const double pi=acos(-1.0); template<class T>inline void rd(T &x){int Finish_read=0;x=0;int f=1;char ch=getchar();while(!isdigit(ch)){if(ch=='-')f=-1;if(ch==EOF)return;ch=getchar();}while(isdigit(ch))x=x*10+ch-'0',ch=getchar();x*=f;Finish_read=1;} template<class T> inline T Maxx(const T&a,const T&b){return a < b?b:a;} template<class T> inline T Minn(const T&a,const T&b){return a < b?a:b;} template<class T> inline T gcd(T a,T b) {return b?gcd(b,a%b):a;} template<class T> inline T lcm(T x,T y) {return x/gcd(x,y)*y;} struct node{ int to;int cnt;ll w; // bool operator <(const node &t)const{ // if(le-ri==t.le-t.ri) // return le<t.le; // else // return le-ri<t.le-t.ri; // } }; struct qnode{int v;//節點idint k;double c;//源節點到v的暫且最短距離 bool operator <(const qnode &r)const{return c>r.c;} }; struct Edge {int to , next;double w ; } e[600010];//bool vis[MAXN][3]; double dist[MAXN][3]; //點的編號從 1 開始int cnt,p[ MAXN ] ; void Add_Edge(const int x ,const int y ,const int w ){e[ ++cnt ] . to = y ;e[ cnt ] . next = p[ x ];e[ cnt ] . w = w ;p[ x ] = cnt ;return ; } inline double f( double X , int N ) {switch( N ) {case 1 : {return X ;break ;}case 2 : {return fabs( 1 / ( 1 - X ) ) ;break ;}case 0 : {return fabs( ( X - 1 ) / X ) ;break ;}}return 0.0 ; } double dinf; void Dijkstra(int start ){//memset(vis,false,sizeof(vis));priority_queue<qnode>que;memset(dist,127,sizeof(dist));while(!que.empty())que.pop();dinf=dist[0][0];dist[start][0]=0;que.push((qnode){start,0,0});while( que.size()){qnode tmp=que.top();que.pop();int u=tmp.v;if(fabs(tmp.c-dist[u][tmp.k])>1e-7)continue;//如果更新過此狀態,就不再放入隊列// vis[u]=true;int nk=(tmp.k+1)%3;for( int i=p[u] ; i ; i = e[ i ].next ){int v=e[ i ].to;double cost=tmp.c+ f(e[ i ].w,nk) ;if( dist[v][nk]> cost){dist[v][nk]=cost;que.push( (qnode){v,nk,cost});}}} } int main(int argc, char** argv) { //freopen("E://dev//input.in","r",stdin); int n,m;scanf("%d%d",&n,&m );int u,v,w ;for(int i=0;i<m;i++){rd(u),rd(v),rd(w);Add_Edge(u,v,w*1.0);Add_Edge(v,u,w*1.0); } Dijkstra(1) ;double ans=Minn(dist[n][0],Minn(dist[n][1],dist[n][2]));if(fabs(ans-dinf)>1e-7)//與初始化的浮點型INF比較大小printf("%.3lf\n",ans);elseputs( "-1" ) ;return 0; }或者把這里改了:
inline double f( double X , int N ) {switch( N ) {case 0 : {return X ;break ;}case 1 : {return fabs( 1 / ( 1 - X ) ) ;break ;}case 2 : {return fabs( ( X - 1 ) / X ) ;break ;}}return 0.0 ; } double dinf; void Dijkstra(int start ){//memset(vis,false,sizeof(vis));priority_queue<qnode>que;memset(dist,127,sizeof(dist));while(!que.empty())que.pop();dinf=dist[0][0];dist[start][2]=0;que.push((qnode){start,2,0});之所以最后三個的代碼(換句話說是倒數第三個? ?和? ?后兩個)之所以有區別(指的是f函數的區別),就是因為傳入的參數
if(d[nex.first][(now.y+1)%3]>now.cost+f(nex.second,now.y))? 倒數第三個? 的代碼是now.y+1%3? 但是算f函數是now.y。。。
倒數第二個,算f函數也是傳的nk(相當于是now.y+1),所以函數體內當然不一樣咯。。。
所以其實實質都是一樣的,,只不過實現方式不一樣而已、、
還有就是while里面的?if(fabs(tmp.c-dist[u][tmp.k])>1e-7)continue;其實可以不用寫、、、只是會稍微慢一點點。
總結
以上是生活随笔為你收集整理的【牛客 - 370H】Rinne Loves Dynamic Graph(分层图最短路)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: PRISMSTA.EXE - PRISM
- 下一篇: 苹果留一手!iPhone 14 Pro独