dreamxr
精诚所至,金石为开!

导航

 

  开始好好学学图论了,以前学过点最小生成树,最短路什么的,不过忘的差不多了....

  准备在这个文章里记录下我做过的最短路问题.....慢慢更新...

1.ZOJ 1298 http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=298

  骨牌结束的时候有两种可能,一种是关键牌最后倒下,一种是普通牌最后倒下.

  先求出起点到每个点的最短路,然后找出这些最短路中最大值maxn1,然后考虑普通牌最后倒下的情况,i和j之间的普通牌全部倒下的时间是(dis[i]+dis[j]+edge[i][j])/2,对每条边求一次,找出最大的maxn2,比较一下即可...

  

Domino Effect
 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 #include<iostream>
 5 #define inf (1<<30)
 6 #define N 510
 7 using namespace std;
 8 int edge[N][N];
 9 int dis[N],n,m;
10 bool s[N];
11 void Dijkstra(){
12     memset(s,0,sizeof(s));
13     for(int i=1;i<=n;i++){
14         dis[i]=edge[1][i];
15     }
16     s[1]=1;dis[1]=0;
17     for(int i=1;i<n;i++){
18         int min=inf,u=1;
19         for(int j=1;j<=n;j++){
20             if(!s[j]&&dis[j]<min){
21                 u=j;
22                 min=dis[j];
23             }
24         }
25         s[u]=1;
26         for(int j=1;j<=n;j++){
27             if(!s[j]&&edge[u][j]<inf&&dis[u]+edge[u][j]<dis[j])
28                 dis[j]=dis[u]+edge[u][j];
29         }
30     }
31 }
32 int main(){
33     int d=1;
34     while(scanf("%d%d",&n,&m)){
35         if(!(n||m))
36         return 0;
37         for(int i=0;i<=n;i++)
38             for(int j=0;j<=n;j++)
39                 edge[i][j]=inf;
40         while(m--){
41             int a,b,c;
42             scanf("%d%d%d",&a,&b,&c);
43             edge[a][b]=edge[b][a]=c;
44         }
45         Dijkstra();
46         double maxn1=-1,maxn2=-1;
47         int pos1,pos2;
48         int pos;
49         for(int i=1;i<=n;i++){
50             if(maxn1<1.0*dis[i]){
51                 maxn1=1.0*dis[i];
52                 pos=i;
53             }
54         }
55         for(int i=1;i<=n;i++)
56             for(int j=1;j<=n;j++){
57                 if(edge[i][j]<inf){
58                     double time=1.0*(dis[i]+dis[j]+edge[i][j])/2.0;
59                     if(time>maxn2){
60                         maxn2=time;
61                         pos1=i;
62                         pos2=j;
63                     }
64                 }
65             }
66         printf("System #%d\n",d++);
67         if(maxn1>=maxn2)
68             printf("The last domino falls after %.1lf seconds, at key domino %d.\n",maxn1,pos);
69         else
70             printf("The last domino falls after %.1lf seconds, between key dominoes %d and %d.\n",maxn2,pos1,pos2);
71         puts("");
72     }
73     return 0;
74 }

 2.ZOJ 1092 http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=92

  利用Bellman求最长路...

Arbitrage
#include<string>
#include<cstring>
#include<iostream>
#include<map>
#define N 100
using namespace std;
struct Edge{
    int u,v;
    double len;
}edge[N*N/2];
double dis[N];
bool flag;
void Bellman(int v0,int n,int m){
    for(int i=1;i<=n;i++) dis[i]=0.0;
    dis[v0]=1;
    flag=0;
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++)
            if(dis[edge[j].v]<dis[edge[j].u]*edge[j].len){
                dis[edge[j].v]=dis[edge[j].u]*edge[j].len;
            }
    }
    if(dis[v0]>1.0)flag=1;
}
int main(){
    int n,m,d=1;
    while(cin>>n){
        if(!n) return 0;
        map<string ,int >M;
        for(int i=1;i<=n;i++){
            string s;
            cin>>s;
            M[s]=i;
        }
        cin>>m;
        for(int i=1;i<=m;i++){
            string s1,s2;
            double x;
            cin>>s1>>x>>s2;
            edge[i].u=M[s1];
            edge[i].len=x;
            edge[i].v=M[s2];
        }
        for(int i=1;i<=n;i++){
            Bellman(i,n,m);
            if(flag) break;
        }
        cout<<"Case "<<d++<<": ";
        if(flag)
            cout<<"Yes"<<endl;
        else
            cout<<"No"<<endl;
    }
    return 0;
}

 3.ZOJ 1655 http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=655

  建图挺有意思感觉...

Transport Goods
 1 #include<cstdio>
 2 #include<cmath>
 3 #include<cstring>
 4 #include<algorithm>
 5 #define N 110
 6 using namespace std;
 7 struct Edge{
 8     int u,v;
 9     double len;
10     Edge(){}
11     Edge(int x,int y,double z):u(x),v(y),len(z){}
12 }edge[N*N];
13 double dis[N],w[N];
14 void Bellman(int n,int m){
15     for(int i=1;i<=n;i++)dis[i]=0;
16     dis[n]=1;
17     bool  f=1;
18     for(int i=1;i<n&&f;i++){
19         f=0;
20         for(int j=0;j<m;j++){
21             if(dis[edge[j].v]<dis[edge[j].u]*edge[j].len){
22                 dis[edge[j].v]=dis[edge[j].u]*edge[j].len;
23                 f=1;
24             }
25         }
26     }
27 }
28 int main(){
29     int n,m;
30     while(~scanf("%d%d",&n,&m)){
31         for(int i=1;i<n;i++)
32             scanf("%lf",&w[i]);
33         int cnt=0;
34         for(int i=1;i<=m;i++){
35             int x,y;double z;
36             scanf("%d%d%lf",&x,&y,&z);
37             edge[cnt++]=Edge(x,y,1.0-z);
38             edge[cnt++]=Edge(y,x,1.0-z);
39         }
40         Bellman(n,cnt);
41         double ans=0;
42         for(int i=1;i<n;i++)
43             ans+=dis[i]*w[i];
44         printf("%.2lf\n",ans);
45     }
46     return 0;
47 }

 4.POJ 3268 http://poj.org/problem?id=3268

  正向反向各求一次..加和之后取最大的就可以了

Silver Cow Party
Source Code

Problem: 3268        User: 920192460
Memory: 4332K        Time: 141MS
Language: C++        Result: Accepted
Source Code
#include<cstdio>
#include<cstring>
#include<queue>
#include<algorithm>
#include<iostream>
#include<vector>
#define N 1010
#define inf (1<<30)
using namespace std;
int edge[N][N];
vector<int>V[N];
int dis[N],ans[N];
bool  used[N];
void SPFA(int st,int n){
    memset(used,0,sizeof(used));
    for(int i=1;i<=n;i++)dis[i]=inf;
    dis[st]=0;
    queue<int>Q;
    Q.push(st);
    used[st]=1;
    while(!Q.empty()){
        int p=Q.front();Q.pop();
        used[p]=0;
        for(int i=0;i<V[p].size();i++){
            int v=V[p][i];
            if(dis[v]-edge[p][v]>dis[p]){
                dis[v]=dis[p]+edge[p][v];
                if(!used[v]){
                    Q.push(v);
                    used[v]=1;
                }
            }
        }
    }
}
int main(){
    int n,m,x;
    while(cin>>n>>m>>x){
        memset(edge,-1,sizeof(edge));
        memset(ans,0,sizeof(ans));
        for(int i=1;i<=n;i++)
            V[i].clear();
        while(m--){
            int a,b,c;
            cin>>a>>b>>c;
            edge[a][b]=c;
            V[a].push_back(b);
        }
        SPFA(x,n);
        for(int i=1;i<=n;i++)
            ans[i]+=dis[i];
        for(int i=1;i<=n;i++)
            V[i].clear();
        for(int i=1;i<=n;i++)
            for(int j=i;j<=n;j++){
                int t=edge[i][j];
                edge[i][j]=edge[j][i];
                edge[j][i]=t;
            }
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++){
                if(i==j||edge[i][j]==-1)continue;
                V[i].push_back(j);
            }
        SPFA(x,n);
        for(int i=1;i<=n;i++)
            ans[i]+=dis[i];
        int maxn=-1;
        for(int i=1;i<=n;i++)
            maxn=max(maxn,ans[i]);
        cout<<maxn<<endl;
    }
    return 0;
}

 

5.ZOJ 1967 http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=967

  Floyd思想..位运算..

Fiber Network
 1 #include<cstdio>
 2 #include<cstring>
 3 #include<string>
 4 #include<iostream>
 5 #define N 210
 6 using namespace std;
 7 int edge[N][N];
 8 void Floyd(int n){
 9     for(int k=1;k<=n;k++)
10         for(int i=1;i<=n;i++)
11             for(int j=1;j<=n;j++)
12                 edge[i][j]|=edge[i][k]&edge[k][j];
13 }
14 int main(){
15     int n,a,b;
16     string s;
17     while(cin>>n){
18         if(!n)return 0;
19         memset(edge,0,sizeof(edge));
20         while(cin>>a>>b){
21             if(!(a||b))break;
22             cin>>s;
23             for(int i=0;i<s.size();i++)
24                 edge[a][b]+=(1<<(s[i]-'a'));
25         }
26         Floyd(n);
27         while(cin>>a>>b){
28             if(!(a||b))break;;
29             if(edge[a][b]){
30                 int ans=edge[a][b],x=0;
31                 while(ans){
32                     if(ans%2){
33                         char m='a'+x;
34                         cout<<m;
35                     }
36                     ans/=2;
37                     x++;
38                 }
39                 cout<<endl;
40             }
41             else
42                 cout<<"-"<<endl;
43         }
44         cout<<endl;
45     }
46     return 0;
47 }

 6.ZOJ 1942 http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=942

  松弛操作比较特殊,对Bellman及SPFA有了新的了解

Frogger
 1 #include<cstdio>
 2 #include<iostream>
 3 #include<cstring>
 4 #include<string>
 5 #include<cmath>
 6 #include<algorithm>
 7 #include<queue>
 8 #define N 210
 9 #define inf (1<<30)
10 using namespace std;
11 double edge[N][N],x[N],y[N];
12 double dis[N];
13 bool used[N];
14 double cal(double x1,double y1,double x2,double y2){
15     return sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
16 }
17 void SPFA(int n){
18     for(int i=1;i<=n;i++)dis[i]=1.0*inf;
19     memset(used,0,sizeof(used));
20     queue<int>Q;
21     dis[1]=0;
22     used[1]=1;
23     Q.push(1);
24     while(!Q.empty()){
25         int p=Q.front();Q.pop();
26         used[p]=0;
27         for(int i=1;i<=n;i++){
28             if(dis[i]>max(dis[p],edge[p][i])){
29                 dis[i]=max(dis[p],edge[p][i]);
30                 if(!used[i]){
31                     used[i]=1;
32                     Q.push(i);
33                 }
34             }
35         }
36     }
37 }
38 int main(){
39     int n,d=1;
40     while(scanf("%d",&n)&&n){
41         for(int i=1;i<=n;i++)
42             scanf("%lf%lf",&x[i],&y[i]);
43         for(int i=1;i<=n;i++)
44             for(int j=1;j<=n;j++)
45                 edge[i][j]=cal(x[i],y[i],x[j],y[j]);
46         SPFA(n);
47         printf("Scenario #%d\n",d++);
48         printf("Frog Distance = %.3lf\n\n",dis[2]);
49     }
50     return 0;
51 }

   另一种用Floyd实现的...

Frogger
 1 #include<cstdio>
 2 #include<iostream>
 3 #include<cstring>
 4 #include<string>
 5 #include<cmath>
 6 #include<algorithm>
 7 #define N 210
 8 using namespace std;
 9 double edge[N][N],x[N],y[N];
10 double dis[N][N];
11 double cal(double x1,double y1,double x2,double y2){
12     return sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
13 }
14 void Floyd(int n){
15     for(int k=1;k<=n;k++)
16         for(int i=1;i<=n;i++)
17             for(int j=1;j<=n;j++){
18         //        if(i==j)continue;
19                 dis[i][j]=min(dis[i][j],max(dis[i][k],dis[k][j]));
20             }
21 }
22 int main(){
23     int n,d=1;
24     while(scanf("%d",&n)&&n){
25         for(int i=1;i<=n;i++)
26             scanf("%lf%lf",&x[i],&y[i]);
27         for(int i=1;i<=n;i++)
28             for(int j=1;j<=n;j++)
29                 dis[i][j]=edge[i][j]=cal(x[i],y[i],x[j],y[j]);
30         Floyd(n);
31         printf("Scenario #%d\n",d++);
32         printf("Frog Distance = %.3lf\n\n",dis[1][2]);
33     }
34     return 0;
35 }

 

 

 

 

 

 

 

posted on 2012-09-04 16:39  dreamxr  阅读(161)  评论(0)    收藏  举报