1. 程式人生 > >kuangbin專題四 最短路練習【從入門到熟練】

kuangbin專題四 最短路練習【從入門到熟練】

clu struct sin img urn star 通路 gif col

【POJ 2253 Frogger】

這道題求從u到v中所有通路的最大邊最小

我直接二分做了,但實際上這種題是最短路算法的變種,意義在於告訴我們spfa這些算法不僅能維護出最短路,稍加修改後可以維護出很多其他東西。

技術分享圖片
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<queue>
#include<string>
#include<stack>
#include<fstream>
#include
<map> #include<iomanip> #include<algorithm> #include<vector> #define INF 2e9 #define maxnode 200000 #define ll long long #define lowbit(x) (x&(-x)) const int mod = 10007; const int MAXN = 2e2 + 10; int dx[4]={0,0,1,-1}; int dy[4]={1,-1,0,0}; using namespace std; struct node{ int
v,d; node(int v1,int d1): v(v1),d(d1) {} }; vector<node> edges[MAXN]; int dist[MAXN],visit[MAXN],n; void spfa(){ for(int i=1;i<=n;i++) dist[i]=INF; dist[1]=0; visit[1]=1; queue<int> q; q.push(1); while( !q.empty() ){ int u = q.front(); q.pop(); visit[u]
=0; for(int i=0;i<edges[u].size();i++){ int v = edges[u][i].v; if( dist[v]>dist[u]+edges[u][i].d ){ dist[v] = dist[u]+edges[u][i].d; if( !visit[v] ) q.push(v); } } } } int x[MAXN],y[MAXN]; double dis[MAXN][MAXN]; int main(){ //ios::sync_with_stdio(false); int tc=0; while(1){ scanf("%d",&n); if(n==0) break; for(int i=1;i<=n;i++) scanf("%d%d",x+i,y+i); for(int i=1;i<=n;i++){ for(int j=1;j<=n;j++){ double x1 = abs(x[i]-x[j]); double y1 = abs(y[i]-y[j]); dis[i][j] = sqrt(x1*x1 + y1*y1); //cout<<i<<" "<<j<<" "<<dis[i][j]<<endl; } } double start=0,end=3000,mid; while( end-start>=0.00001 ){ mid = (start+end)/2; for(int i=1;i<=n;i++) edges[i].clear(); for(int i=1;i<=n;i++){ for(int j=1;j<=n;j++){ if( mid>=dis[i][j] ) edges[i].push_back( node(j,1) ); } } spfa(); if( dist[2]!=INF ) end=mid; else start=mid; } printf("Scenario #%d\n",++tc); printf("Frog Distance = %.3lf\n",end); printf("\n"); } return 0; }
View Code

【POJ 1797 Heavy Transportation】

維護所有通路的最小邊最大

那修改後的松弛操作就是 dist[v] = max( dist[v], min( dist[u], edges[u][i].d ) )

技術分享圖片
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<queue>
#include<string>
#include<stack>
#include<fstream>
#include<map>
#include<iomanip> 
#include<algorithm>
#include<vector>
#define INF 2e9
#define maxnode 200000
#define ll long long
#define lowbit(x) (x&(-x))
const int mod = 10007;
const int MAXN = 1e3 + 10;
int dx[4]={0,0,1,-1};
int dy[4]={1,-1,0,0};
using namespace std;

struct node{
    int v,d;
    node(int v1,int d1): v(v1),d(d1) {}
};

vector<node> edges[MAXN];

int dist[MAXN],visit[MAXN],n,m;//dist[i]代表從源點到i點中所有通路的最小邊最大值 
void spfa(){
    for(int i=1;i<=n;i++) dist[i]=0;
    dist[1]=INF; visit[1]=1;
    queue<int> q;
    q.push(1);
    while( !q.empty() ){
        int u = q.front(); q.pop();
        visit[u]=0;
        for(int i=0;i<edges[u].size();i++){
            int v = edges[u][i].v;
            int weight = min( edges[u][i].d,dist[u] );//weight是這條通路上的最小邊 
            if( weight>dist[v] ){
                dist[v] = weight;
                if( !visit[v] ) {
                    //visit[v]=1;
                    q.push(v);
                }
            }
        }
    }
    
}

//找所有通路中最小邊最大的 
int main(){
    //ios::sync_with_stdio(false);
    int t,tc=0; scanf("%d",&t); 
    while(t--){
        scanf("%d%d",&n,&m);
        for(int i=1;i<=m;i++){
            int u,v,d; scanf("%d%d%d",&u,&v,&d);
            edges[u].push_back( node(v,d) );
            edges[v].push_back( node(u,d) );
        }
        
        spfa();
        printf("Scenario #%d:\n",++tc);
        printf("%d\n",dist[n]);
        printf("\n");
        
        for(int i=1;i<=n;i++) edges[i].clear();
    }    
    
    return 0;
}
View Code

【POJ 3268 Silver Cow Party】

想到跑flyod但n^3太慢就t了,實際上反向建邊跑兩邊spfa就可以了!

技術分享圖片
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<queue>
#include<string>
#include<stack>
#include<fstream>
#include<map>
#include<iomanip> 
#include<algorithm>
#include<vector>
#define INF 2e9
#define maxnode 200000
#define ll long long
#define lowbit(x) (x&(-x))
const int mod = 10007;
const int MAXN = 1e3 + 10;
int dx[4]={0,0,1,-1};
int dy[4]={1,-1,0,0};
using namespace std;

struct node{
    int v,d;
    node(int v1,int d1): v(v1),d(d1) {}
};
vector<node> edges[MAXN];
int vis[MAXN],dist1[MAXN],dist2[MAXN],n,m,x;

void spfa1(){
    for(int i=1;i<=n;i++) dist1[i]=INF;
    queue<int> q;
    q.push(x); vis[x]=1; dist1[x]=0;
    while(!q.empty()){
        int u = q.front(); q.pop();
        vis[u]=0;
        for(int i=0;i<edges[u].size();i++){
            int v = edges[u][i].v;
            int d = edges[u][i].d;
            if( dist1[u]+d<dist1[v] ){
                dist1[v]=dist1[u]+d;
                if( !vis[v] ){
                    q.push(v);
                    vis[v]=1;
                }
            }
        }
    }    
}

void spfa2(){
    for(int i=1;i<=n;i++) dist2[i]=INF;
    queue<int> q;
    q.push(x); vis[x]=1; dist2[x]=0;
    while(!q.empty()){
        int u = q.front(); q.pop();
        vis[u]=0;
        for(int i=0;i<edges[u].size();i++){
            int v = edges[u][i].v;
            int d = edges[u][i].d;
            if( dist2[u]+d<dist2[v] ){
                dist2[v]=dist2[u]+d;
                if( !vis[v] ){
                    q.push(v);
                    vis[v]=1;
                }
            }
        }
    }
    
}

int u[100005],v[100005],d[100005];


int main(){
    //ios::sync_with_stdio(false);
    while( scanf("%d%d%d",&n,&m,&x)!=EOF ){
        
        for(int i=1;i<=m;i++){
            scanf("%d%d%d",u+i,v+i,d+i);
            edges[ u[i] ].push_back( node(v[i],d[i]) );
        }
        
        spfa1();
        for(int i=1;i<=n;i++) edges[i].clear();    
        for(int i=1;i<=m;i++) edges[ v[i] ].push_back( node(u[i],d[i]) );
        spfa2();
        
        int ans=-1;
        for(int i=1;i<=n;i++){//枚舉所有cows
            ans = max( ans,dist1[i]+dist2[i] );
        }
        printf("%d\n",ans);
        
        for(int i=1;i<=n;i++) edges[i].clear();            

    }    
    
    return 0;
}
View Code

【】

技術分享圖片
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<queue>
#include<string>
#include<stack>
#include<fstream>
#include<map>
#include<iomanip> 
#include<algorithm>
#include<vector>
#define INF 2e9
#define maxnode 200000
#define ll long long
#define lowbit(x) (x&(-x))
const int mod = 10007;
const int MAXN = 1e2 + 10;
int dx[4]={0,0,1,-1};
int dy[4]={1,-1,0,0};
using namespace std;

struct exchange{
    int type;
    double r,c;
    exchange(int t1,double r1,double c1): type(t1),r(r1),c(c1) {}
};

vector<exchange> edges[MAXN];//edges[i]是拿著i貨幣能選擇的一些兌換方案 

double d[MAXN],money;
int n,m,s;

struct node{
    int type;
    double m;//狀態是拿著m個type錢
    node(int t1,double m1): type(t1),m(m1) {} 
};

bool bfs(){
    for(int i=1;i<=n;i++) d[i]=-INF;//最優性剪枝,d[i]為i種貨幣最多有多少個 
    queue<node> q;
    q.push( node(s,money) ); d[s]=money;
    while( !q.empty() ){
        node p = q.front(); q.pop();
        if( p.type==s && p.m>money ) return true;
        for(int i=0;i<edges[p.type].size();i++){//能怎麽換 
            exchange e = edges[p.type][i];//在這個所換 
            double m1 = (p.m-e.c)*e.r;
            if( m1>d[ e.type ] ){
                d[e.type]=m1;
                q.push( node(e.type,m1) );
            }
        }
    }

    return false;
}

int main(){
    //ios::sync_with_stdio(false);
    while( scanf("%d%d%d%lf",&n,&m,&s,&money)!=EOF ){
        
        for(int i=1;i<=m;i++){
            int a,b; 
            double r1,c1,r2,c2; scanf("%d%d%lf%lf%lf%lf",&a,&b,&r1,&c1,&r2,&c2);
            edges[a].push_back( exchange(b,r1,c1) );
            edges[b].push_back( exchange(a,r2,c2) );
        }
        
        if( bfs() ) printf("YES\n");
        else printf("NO\n");
        
        for(int i=1;i<=n;i++) edges[i].clear();
    }    
    
    return 0;
}
View Code

kuangbin專題四 最短路練習【從入門到熟練】