1. 程式人生 > >刷題總結——做運動(NOIP模擬)

刷題總結——做運動(NOIP模擬)

time 復雜度 bsp i++ top oid reg 第一次 現在

題目:

給定一個無向圖,節點數n<=50000,m<=1000000,每條邊有兩個值t和c,邊的長度為t*c···現在要求再t盡量小的情況下,求兩節點st的最短距離

題解:

第一次做的時候想都沒有想直接用二分+迪傑斯特拉了···哎連復雜度都算不來了···

正解應該是將邊按t升序排序後跑kruskals····用並差集判st是否連通··一旦聯通將t值小於等於目前枚舉的t值的邊全部加入建圖然後跑最短路就可以了···

其實如果考試時仔細想一想時是可以想到正解的··畢竟如果t要盡量小的話不是二分就是最小生成樹了···但並差集判連通性這一點已經很久每用過了··這題算是提了醒吧··

代碼:

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<ctime>
#include<cctype>
#include
<cstring> #include<string> #include<algorithm> #include<queue> using namespace std; priority_queue< pair<long long,int> >que; const int N=5e5+5; const int M=1e6+5; inline int R() { char c;int f=0; for(c=getchar();c<0||c>9;c=getchar()); for
(;c<=9&&c>=0;c=getchar()) f=(f<<3)+(f<<1)+c-0; return f; } struct node { int x,y,T,C; inline friend bool operator < (node a,node b) { return a.T<b.T; } }edge[M]; int Father[N],fst[N],go[M*2],nxt[M*2],n,m,src,des,anst,tot; long long dis[N],val[M*2]; inline bool comb(int a,int b,int c,int d) { nxt[++tot]=fst[a],fst[a]=tot,go[tot]=b,val[tot]=(long long)c*d; nxt[++tot]=fst[b],fst[b]=tot,go[tot]=a,val[tot]=(long long)c*d; } inline int get(int a) { if(Father[a]==a) return a; else return Father[a]=get(Father[a]); } inline void solve() { for(register int i=1;i<=n;i++) dis[i]=2e+18; dis[src]=0;que.push(make_pair(0,src)); while(!que.empty()) { int u=que.top().second;que.pop(); if(u==des) break; for(register int e=fst[u];e;e=nxt[e]) { int v=go[e]; if(dis[v]>dis[u]+val[e]) { dis[v]=dis[u]+val[e]; que.push(make_pair(-dis[v],v)); } } } } int main() { //freopen("a.in","r",stdin); n=R();m=R(); for(register int i=1;i<=n;i++) Father[i]=i; for(register int i=1;i<=m;i++) edge[i].x=R(),edge[i].y=R(),edge[i].T=R(),edge[i].C=R(); src=R();des=R(); sort(edge+1,edge+m+1); for(register int i=1;i<=m;i++) { int fx=get(edge[i].x),fy=get(edge[i].y); Father[fx]=fy; if(get(src)==get(des)) { anst=edge[i].T; break; } } cout<<anst<<" "; for(register int i=1;i<=m;i++) { if(edge[i].T>anst) break; comb(edge[i].x,edge[i].y,edge[i].T,edge[i].C); } solve();cout<<dis[des]<<endl; return 0; }

刷題總結——做運動(NOIP模擬)