【最小路径】

/*
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 0x7fffffff
struct 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 2139
N头牛,拍了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 101
using 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 0x3f3f3f3f
using 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, cba
2 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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供的源码资源涵盖了安卓应用、小程序、Python应用和Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值