【最小路径】
来源:互联网 发布:知乎看见了女朋友 编辑:程序博客网 时间:2024/05/19 13:23
/*POJ 3268题目大意是给出一个有向图的带权邻接矩阵,然后给定目标节点X,求出其余结点出发到结点X再从X回到出发结点的最短路径和中最大的那个...把矩阵转置一下就好了,转置以后就又相当于从X出发了,再来一次Dijkstra搞定...很好理解的..*/#include<cstdio>#include<cstring>using namespace std;const int N=1010;const int MAX=1000001;int n,m;int map1[N][N];int map2[N][N],visited[N];int dist1[N],dist2[N];void dijkstra(int mapx[][N],int dist[],int x){//最短路径 int u,minx; for(int i=1;i<=n;i++) dist[i]=mapx[x][i]; memset(visited,0,sizeof(visited)); visited[x]=1; for(int i=1;i<=n;i++){ u=x,minx=MAX; for(int j=1;j<=n;j++){ if(!visited[j]&&dist[j]<minx){ minx=dist[j]; u=j; } } visited[u]=1; for(int j=1;j<=n;j++){ if(!visited[j]&&dist[j]>dist[u]+mapx[u][j]) dist[j]=dist[u]+mapx[u][j]; } }}int main(){ int ai,bi,ti,x; int ans=0; scanf("%d%d%d",&n,&m,&x); for(int i=1;i<=n;i++){//初始化 for(int j=1;j<=n;j++){ if(i==j) { map1[i][j]=0; map2[j][i]=0; } else { map1[i][j]=MAX; map2[j][i]=MAX; } } } for(int i=1;i<=m;i++){ scanf("%d%d%d",&ai,&bi,&ti); map1[ai][bi]=ti; map2[bi][ai]=ti;//转置矩阵 } dijkstra(map1,dist1,x); dijkstra(map2,dist2,x); for(int i=1;i<=n;i++){ if(ans<dist1[i]+dist2[i]) ans=dist1[i]+dist2[i]; } printf("%d\n",ans);}
/*题目要我们求是否存在一条路,FJ重新回到起点之后时间回到了过去,就是让我们判断在图中是否存在负权回路。我用了SPFA,当一个点入队超过n次时,可以判断图中存在负权回路。注意图中的前m条路是双向的,注意处理后面的w条虫洞是单向的。POJ 3259*/#include<cstdio>#include<queue>#include<vector>#include<algorithm>using namespace std;#define MAXN 550#define INF 0x7fffffffstruct node{ int to;//终点 int dis;//距离};bool in[MAXN];//是否在队列int counts[MAXN],dis[MAXN],n,m,w;// counts入队的次数、dis最短的距离vector<node>g[MAXN];bool spfa(int s){//模板题 queue<int>q; for(int i=1;i<=n;i++){ dis[i]=INF; counts[i]=0; in[i]=false; } dis[s]=0; counts[s]=1; in[s]=true; q.push(s); while(!q.empty()){ int tag=q.front(); q.pop(); in[tag]=false; for(int i=0;i<g[tag].size();i++){ int j=g[tag][i].to; if(g[tag][i].dis+dis[tag]<dis[j]){//更新路径 dis[j]=g[tag][i].dis+dis[tag]; if(!in[j]){//不在队列入队 in[j]=true; counts[j]++; if(counts[j]>=n)//存在负环路 return false; q.push(j); } } } } return true;}void init(){ //初始化数据 scanf("%d%d%d",&n,&m,&w); int x,y,d; node temp; for(int i=0;i<=n;i++)//清空操作 g[i].clear(); for(int i=1;i<=m;i++){ scanf("%d%d%d",&x,&y,&d);//双向边 temp.to=y; temp.dis=d; g[x].push_back(temp); temp.to=x; g[y].push_back(temp); } for(int i=1;i<=w;i++){ scanf("%d%d%d",&x,&y,&d);//单向边 只能回到过去 temp.to=y; temp.dis=-d; g[x].push_back(temp); }}int main(){ int t ; scanf("%d",&t); while(t--){ init(); if(spfa(1)) printf("NO\n"); else printf("YES\n"); }}
/*POJ 2139N头牛,拍了M部电影,同一部电影中的搭档们距离1,求最小度数之和。题解:flyod最短路,枚举找最小warshall_floyd算法,求任意两点间的最短路 O(V^3)dp[i][j] = e(i, j)的权值(不存在为Inf,dp[i][i] = 0)*/#include<cstdio>#include<cstring>#include<algorithm>using namespace std;const int inf=0x3f3f3f3f;int n,m,dp[303][303];void warshall_floyd(){ //模板 for(int k=1;k<=n;k++) for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) dp[i][j]=min(dp[i][j],dp[i][k]+dp[k][j]);}int main(){ int ans=inf; scanf("%d%d",&n,&m); //初始化 memset(dp,inf,sizeof(dp)); for(int i=1;i<n;i++) dp[i][i]=0; while(m--){ int a,b[303]; scanf("%d",&a); for(int i=0;i<a;i++) scanf("%d",&b[i]); for(int i=0;i<a-1;i++) for(int j=i+1;j<a;j++){ dp[b[i]][b[j]]=dp[b[j]][b[i]]=1; } } warshall_floyd(); for(int i=1;i<=n;i++){//枚举类型 int sum=0; for(int j=1;j<=n;j++) sum+=dp[i][j]; ans=min(ans,sum); } printf("%d\n",ans*100/(n-1));}
/*POJ 1062最短路径——Dijkstra算法此题的关键在于等级限制的处理,最好的办法是采用枚举,即假设酋长等级为5,等级限制为2,那么需要枚举等级从3~5,4~6,5~7从满足改等级范围的结点组成的子图中用Dijkstra来算出最短路径小结,通过枚举的方式可以消除一些图与图之间的限制[lev-M,lev],[lev-M+1,lev+1],... ...,[lev,lev+M]*/#include<cstdio>#include<cmath>#include<cstring>#include<algorithm>using namespace std;#define INF 0x3f3f3f3f#define MAXN 101using namespace std;int dict[MAXN][MAXN],lev[MAXN],d[MAXN],value[MAXN];bool within_lim[MAXN],v[MAXN];//within_lim为满足等级限制的标记数组int lev_lim,n;int dijkstra(){ int mininum=INF; memset(v,0,sizeof(v));//清除所有点的标号 for(int i=1;i<=n;i++)//设d[0] = 0,其他d[i] = INF d[i]=(i==1?0:INF); for(int i=1;i<=n;i++){//循环N次 int x=0,m=INF; for(int j=1;j<=n;j++){ if(!v[j]&&d[j]<=m&&within_lim[j]){//在所有未标号且满足等级限制的结点中,选出d值最小的结点x x=j; m=d[j]; } } v[x]=1;//给结点x标记 for(int j=1;j<=n;j++){ if(within_lim[j]){//对于从x出发的所有边(x,y),更新d[y] = min{d[y], d[x] + map[x][y]) d[j]=min(d[j],d[x]+dict[x][j]);//满足等级限制 } } } for(int i=1;i<=n;i++){ d[i]+=value[i]; if(d[i]<mininum)//对于每个d[i]值,还需加上进入该结点的花费,再进行比较 mininum=d[i]; } return mininum;}int main(){ scanf("%d%d",&lev_lim,&n); for(int i=0;i<=n;i++) for(int j=0;j<=n;j++) dict[i][j]=(i==j?0:INF);//图的初始化,注意对角线初始化为0,从自己出发到自己的花费为0 for(int i=1;i<=n;i++){ int t; scanf("%d%d%d",&value[i],&lev[i],&t); for(int j=1;j<=t;j++){ int k; scanf("%d",&k); scanf("%d",&dict[i][k]); }//建图完毕 } int kinglev=lev[1]; int min_cost=INF,cost; for(int i=0;i<=lev_lim;i++){ memset(within_lim,0,sizeof(within_lim));//初始化标记数组 for(int j=1;j<=n;j++){//枚举等级允许范围的结点 if(lev[j]>=kinglev-lev_lim+i&&lev[j]<=kinglev+i) within_lim[j]=1; } cost=dijkstra(); if(cost<min_cost) min_cost=cost; } printf("%d\n",min_cost);}
/*POJ 2240*/#include<cstdio>#include<map>#include<string>#define INF 0x3f3f3f3fusing namespace std;char money[30];char change1[30],change2[30];double trans;double dict[50][50];int n,m;map<string,int>p;//用map建立字符串与编号之间的关系(巧用)void Floyd(){ for(int k=1;k<=n;k++) for(int i=1;i<=n;i++) for(int j=1;j<=n;j++){ if(dict[i][j]<dict[i][k]*dict[k][j]) //变形的最大路径 把‘+’变为了‘*’ dict[i][j]=dict[i][k]*dict[k][j]; }}void solve(){ int cnt=1; while(~scanf("%d%*c",&n)&&n){ for(int i=1;i<=n;i++){ scanf("%s",money); p[money]=i; dict[i][i]=1; } scanf("%d%*c",&m); for(int i=1;i<=m;i++){ scanf("%s%lf%s",change1,&trans,change2); dict[p[change1]][p[change2]]=trans; } Floyd(); bool flag=false; for(int i=1;i<=n;i++){ if(dict[i][i]>1){ flag=true; break; } } if(flag) { printf("Case %d: Yes\n", cnt++); } else { printf("Case %d: No\n", cnt++); } }}int main(){ solve(); return 0;}
/*POJ 1860题意 : 就是套汇的问题,汇率Rab, 增加了一个手续费 Cab 。。。。。。。每次的结果是 (本金 - 手续费) * 汇率,而且一个人拥有的钱的类型是已知的,拥有的value 钱的个数也是已知的, 问你能不能增值。输入 :3 2 1 20.0 //钱种类个数 汇率的个数,拥有第几种钱, 拥有多少钱1 2 1.00 1.00 1.00 1.00 //钱a, 钱b, rab, cab, rba, cba2 3 1.10 1.00 1.10 1.00*/#include<cstdio>#include<cstring>#include<algorithm>using namespace std;struct Edge{ int s,e; double r; double c;}edge[210];int k;int N,M,S;double V;double dis[110];bool bellman_ford(){ bool sign; memset(dis,0,sizeof(dis)); dis[S]=V; for(int j=0;j<N+1;j++){//N+1 如果每次都有改变的话,说明一定存在环路。 sign=false; for(int i=0;i<k;i++){ if(dis[edge[i].e]<(dis[edge[i].s]-edge[i].c)*edge[i].r){ dis[edge[i].e]=(dis[edge[i].s]-edge[i].c)*edge[i].r; sign=true; } } if(!sign) break; } if(sign) return false; else return true;}int main(){ while(~scanf("%d%d%d%lf",&N,&M,&S,&V)){ k=0; int a,b; double rab,cab,rba,cba; for(int i=0;i<M;i++){ scanf("%d%d%lf%lf%lf%lf",&a,&b,&rab,&cab,&rba,&cba); edge[k].s=a; edge[k].e=b; edge[k].r=rab; edge[k++].c=cab; edge[k].s=b; edge[k].e=a; edge[k].r=rba; edge[k++].c=cba; } if(bellman_ford()) puts("NO"); else puts("YES"); }}
/*POJ 2253//如果存在路径,则选择路径中最长的边来更新即可*/#include<cstdio>#include<cmath>#include<cstring>#include<algorithm>using namespace std;const int maxn=210;const double MAX=2000;double dict[maxn][maxn];double dis[maxn];int visited[maxn];int n;double ans;struct Point{ double x,y;}p[maxn];double dist(Point a,Point b){ return sqrt((a.x-b.x)*(a.x-b.x) + (a.y-b.y)*(a.y-b.y));}void Dijkstra(){ for(int i=1;i<=n;i++) dis[i]=MAX; dis[1]=0; memset(visited,0,sizeof(visited)); for(int i=1;i<=n;i++){ int x; double minx=MAX; for(int j=1;j<=n;j++){ if(!visited[j]&&dis[j]<=minx){ minx=dis[j]; x=j; } } visited[x]=1; if(ans<dis[x]&&dis[x]!=MAX) ans=dis[x]; if(x==2) return ; for(int j=1;j<=n;j++){ if(!visited[j]) dis[j]=min(dis[j],dict[x][j]); } }}int main(){ int kcase=0; while(scanf("%d",&n),n){ for(int i=1;i<=n;i++) scanf("%lf%lf",&p[i].x,&p[i].y); for(int i=1;i<=n;i++){ dict[i][i]=0; for(int j=i+1;j<=n;j++){ dict[i][j] = dist(p[i],p[j]); dict[j][i] = dist(p[i],p[j]); } } ans=0; Dijkstra(); printf("Scenario #%d\n", ++kcase); printf("Frog Distance = %.3lf\n\n", ans); }}
0 0
- 【最小路径】
- 最小路径
- 【最小路径覆盖】最小路径覆盖
- 最小路径覆盖
- 最小路径覆盖
- pku2594 最小路径覆盖
- 最小路径覆盖
- Dijkstra最小路径
- 最小路径覆盖
- poj1422最小路径覆盖
- 最小路径覆盖
- 最小路径覆盖:Divisibility
- poj1422最小路径覆盖
- 最小路径覆盖
- poj2060 最小路径覆盖
- 最小路径覆盖
- 最小路径覆盖
- poj2060最小路径覆盖
- hdu-3401-Trade-单调队列优化的DP
- HDU 1789 Doing Homework again
- 小米路由器探测和测评本人亲测
- ci框架mysql数据库连接资源无法释放
- 逗比linux命令行
- 【最小路径】
- LeetCode Jump Game II
- kaldi中的在线识别----Online Recognizers
- hdu1754I Hate It
- JDBC异常 数据库表不存在
- hdu 2473 并差集
- 可重入和不可重入函数
- 01-package 01背包
- 【NoisyHeart的炼成】Part 8:总结