1. 程式人生 > 實用技巧 >P5837 [USACO19DEC]Milk Pumping G (單源最短路,dijkstra)

P5837 [USACO19DEC]Milk Pumping G (單源最短路,dijkstra)

  • 題意:有一\(n\)個點,\(m\)條邊的雙向圖,每條邊都有花費和流量,求從\(1\)~\(n\)的路徑中,求\(max\frac{min(f)}{\sum c}\).

  • 題解:對於c,一定是單源最短路,我們可以用dijkstra,但是這個最小流量不是很好搞,但是題目所給的資料範圍較小,所以我們可以直接列舉最小流量,然後每次初始化陣列跑dijkstra,去找大於當前最小流量的邊,如果\(1\)~\(n\)有路徑能走,我們每次維護答案的最小值.

  • 程式碼:

    struct misaka{
    	int out;
    	int val;
    	int flow;
    }p;
     
    int n,m;
    int dis[N];
    bool st[N];
    vector<misaka> v[N];
     
    void dijkstra(int x){
    	for(int i=1;i<=n;++i){
    		dis[i]=INF;
    		st[i]=false;
    	}
    	dis[1]=0;
    	priority_queue<PII,vector<PII>,greater<PII>> h;
    	h.push({0,1});
    
    	while(!h.empty()){
    		auto tmp=h.top();
    		h.pop();
    
    		int num=tmp.se;
    		int dist=tmp.fi;
    		if(st[num]) continue;
    		st[num]=true;
    		for(auto w:v[num]){
    			if(x>w.flow) continue;
    			int j=w.out;
    			if(dist+w.val<dis[j]){
    				dis[j]=dist+w.val;
    				h.push({dis[j],j});
    			}
    		}
    	}
    }
    
    int main() {
        ios::sync_with_stdio(false);cin.tie(0);
      	cin>>n>>m;
      	for(int i=1;i<=m;++i){
      		int a,b;
      		cin>>a>>b;
      		cin>>p.val>>p.flow;
      		p.out=b;
      		v[a].pb(p);
      		p.out=a;
      		v[b].pb(p);
      	}
      	int ans=0;
      	for(int i=1;i<=1000;++i){
      		dijkstra(i);
      		if(dis[n]!=INF) ans=max(ans,i*1000000/dis[n]);
      	}
    
      	cout<<ans<<endl;
    
        return 0;
    }