开始好好学学图论了,以前学过点最小生成树,最短路什么的,不过忘的差不多了....
准备在这个文章里记录下我做过的最短路问题.....慢慢更新...
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 }

浙公网安备 33010602011771号