zoukankan      html  css  js  c++  java
  • 最短路练习

    9021#1259香甜的黄油

    题目描述

    农夫John发现做出全威斯康辛州最甜的黄油的方法:糖。把糖放在一片牧场上,他知道N(1<=N<=500)只奶牛会过来舔它,这样就能做出能卖好价钱的超甜黄油。当然,他将付出额外的费用在奶牛上。 
    农夫John很狡猾。像以前的Pavlov,他知道他可以训练这些奶牛,让它们在听到铃声时去一个特定的牧场。他打算将糖放在那里然后下午发出铃声,以至他可以在晚上挤奶。
    农夫John知道每只奶牛都在各自喜欢的牧场(一个牧场不一定只有一头牛)。给出各头牛在的牧场和牧场间的路线,找出使所有牛到达的路程和最短的牧场(他将把糖放在那)。

    输入格式

    第一行: 三个数:奶牛数N,牧场数(2<=P<=800),牧场间道路数C(1<=C<=1450)。
    第二行到第N+1行: 1到N头奶牛所在的牧场号。
    第N+2行到第N+C+1行: 每行有三个数:相连的牧场A、B,两牧场间距离D(1<=D<=255),当然,连接是双向的。

    输出格式

    一行输出奶牛必须行走的最小的距离和。

    样例

    样例输入1

    3 4 5
    2
    3
    4
    1 2 1
    1 3 5
    2 3 7
    2 4 3
    3 4 5

    样例输出1

    8

    数据范围与提示


    {样例图形


    P2
    P1 @--1--@ C1
    |
    |
    5 7 3
    |
    | C3
    C2 @--5--@
    P3 P4
    }

    {样例输出说明:

      放在4号牧场最优

    } 
    模板题了。稍微有点背景。
    很好过,不多说。

    给出点权。边权全部为1。求设在哪个牧场,牛的总移动距离最短。

    无论是Floyd还是dijistra,都要有一步假设这个牧场为答案进行计算。不算不知道啊,所以几个牧场,几次计算。

    对于Floyd,直接计算;对于dijstra,几个牧场,要跑几次单源最短路径,然后计算。

    Floyd            

    dijstra+堆优化

    真是快的一批。。

     1 #include <iostream>
     2 #include <cstdio>
     3 #define R register
     4 #define INF 0x7fffffff
     5 using namespace std;
     6 int ans=INF;
     7 int n,p,c,g[810][810],a[510];
     8 inline int ri(){
     9     char c=getchar();int x=0,w=1;
    10     while(!isdigit(c)){if(c=='-')w=-1;c=getchar();}
    11     while( isdigit(c)){x=(x<<3)+(x<<1)+c-48;c=getchar();}
    12     return x*w;
    13 }
    14 int main(){
    15     int num,x,y;
    16     for(R int i=1;i<=800;++i)
    17     for(R int j=1;j<=800;++j)
    18         g[i][j]=1000000;
    19             
    20     for(R int i=1;i<=800;++i)
    21         g[i][i]=0;
    22             
    23     n=ri(),p=ri(),c=ri();
    24     for(R int i=1;i<=n;++i)
    25         num=ri(),a[num]++;
    26             
    27     for(R int i=1;i<=c;++i)
    28         x=ri(),y=ri(),num=ri(),g[x][y]=g[y][x]=num;
    29     
    30     for(R int k=1;k<=p;++k)
    31     for(R int i=1;i<=p;++i)
    32     for(R int j=1;j<=p;++j)   
    33         if(g[i][k]+g[k][j]<g[i][j])g[i][j]=g[i][k]+g[k][j];
    34       for(R int i=1;i<=p;++i){
    35           int tot=0;
    36           for(R int j=1;j<=p;++j)tot+=g[i][j]*a[j];
    37         ans=min(ans,tot);
    38     }
    39       printf("%d",ans);
    40       return 0;
    41 }
     1 #include <iostream>
     2 #include <cstdio>
     3 #include <queue>
     4 #include <vector>
     5 #define MN 1000
     6 #define R register
     7 #define INF 0x7fffffff
     8 using namespace std;
     9 int n,m,c,d[MN],a[MN];
    10 typedef pair<int ,int> p;
    11 struct edge{int to,cost;};
    12 vector <edge> G[MN];
    13 inline int ri(){
    14     char c=getchar();int x=0,w=1;
    15     while(!isdigit(c)){if(c=='-')w=-1;c=getchar();}
    16     while( isdigit(c)){x=(x<<3)+(x<<1)+c-48;c=getchar();}
    17     return x*w;
    18 }
    19 inline void dijstra(int x){
    20     priority_queue<p,vector<p>,greater<p> >que;
    21     fill(d+1,d+m+1,INF);
    22     d[x]=0,que.push(p(0,x));//d[i],i
    23     while(!que.empty()){
    24         p q=que.top();que.pop();
    25         int v=q.second;
    26         if(d[v]<q.first)continue;
    27         for(R int i=0;i<G[v].size();++i){
    28             edge e=G[v][i];
    29             if(d[e.to]>d[v]+e.cost){
    30                 d[e.to]=d[v]+e.cost;
    31                 que.push(p(d[e.to],e.to));
    32             }
    33         }
    34     }
    35 }
    36 int main(){
    37     int num,x,y,z;
    38     n=ri(),m=ri(),c=ri();//奶牛数N,牧场数m,牧场间道路数C
    39     for(R int i=1;i<=n;++i)num=ri(),a[num]++;
    40     for(R int i=1;i<=c;++i){
    41         x=ri(),y=ri(),z=ri();
    42         edge e={y,z},u={x,z};
    43         G[x].push_back(e);
    44         G[y].push_back(u);
    45     }
    46     int ans=INF;
    47     for(R int i=1;i<=m;++i){
    48         int tot=0;
    49         dijstra(i);
    50         for(R int j=1;j<=m;++j)tot+=a[j]*d[j];
    51         ans=min(ans,tot);
    52     }
    53     printf("%d",ans);
    54 } 

    9021#1519最短路径

    题目描述

    相信对于最短路这个问题,你已经熟练掌握了。现在你有一个新的挑战:计算 Nya 图 上从 1 到 n 的最短路径。 Nya 图的定义如下:Nya 图是一种无向图。图中的每个节点属于一个层 x(1≤x≤n), 共有 n 个节点。 你可以从层 x(1≤x≤n-1) 的任何节点到达层 x + 1 的任何节点,花费为 C,因为道 路是双向的,从层 x + 1(1≤x≤n-1) 的任何节点到达层 X 的任何节点也是相同的花费。 注意,有的层可能有多个节点,有的层可能一个节点都没有。 此外,有额外的 m 条边,每条边连接一对节点 u 和 v,通过的花费为 w。 现在请你帮助我们完成从节点 1 到节点 n 的最短路径的计算,使得路径的花费和最 小。

    输入格式

    从 nyagraph.in 中输入数据 输入有多组数据。 第一行,一个整数 T 表示数据组数。 对于每组数据,第一行为三个整数 n,m,C。 第二行为 n 个整数,第 i 个数表示第 i 个节点属于的层 xi(1≤xi≤n) 接下来 M 行,每行 3 个整数 u,v,w(1≤u,v≤n,u≠v),表示一条额外边。 每组数据间有一个空行。

    输出格式

    输出到 nyagraph.out 中 对于每组数据,各输出一行。 每行先输出“Case #X:”,其中 X 为第几组数据,然后输出一个整数表示最小花费, 若不存在从 1 到 n 的最短路,输出-1。

    样例

    样例输入1

    2
    3 3 3
    1 3 2
    1 2 1
    2 3 1
    1 3 3
    3 3 3
    1 3 2
    1 2 2
    2 3 2
    1 3 4

    样例输出1

    Case #1: 2
    Case #2: 3

    数据范围与提示

    对于 30% 的数据:n≤100,m≤100,T = 1。
    对于 70% 的数据:n≤1000,m≤10000。
    对于 100% 的数据:n≤100000,m≤100000,1≤C≤10^3,1≤w≤10^4,T≤5。

    这题只比模板多了一步复杂的预处理。emmm稍微复杂的??

    同一层的点,距离为0;与之相邻上下两层的点,距离为C。

    于是就有一串恶心的edge e,ee,eee,eeee。。。

    看着ppt码了个dijkstra(当然略有不同,变量名码风七七八八的,因为肯定不是看着打的...),

    以及百度了一个spfa。spfa快...可能我写的丑。

    dijkstra:

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <queue>
     4 #include <vector>
     5 #define R register
     6 #define INF 0x7fffff
     7 using namespace std;
     8 int n,m,c,T,t;
     9 int num[100001],d[300111];
    10 struct edge{int to,cost;};
    11 vector<edge> G[300111];
    12 typedef pair<int ,int> p;
    13 inline void dijkstra(int x){
    14     priority_queue<p,vector<p>,greater<p> >que;
    15     for(R int i=1;i<=n*3+2;++i)d[i]=INF;
    16     d[x]=0;que.push(p(0,x));
    17     while(!que.empty()){
    18         p q=que.top();que.pop();
    19         int v=q.second;
    20         if(d[v]<q.first)continue;
    21         for(R int i=0;i<G[v].size();++i){
    22             edge e=G[v][i];
    23             if(d[e.to]>d[v]+e.cost){
    24                 d[e.to]=d[v]+e.cost;
    25                 que.push(p(d[e.to],e.to));
    26             }
    27         }
    28     }
    29 }
    30 inline int ri(){
    31     char c=getchar();int x=0,w=1;
    32     while(!isdigit(c)){if(c=='-')w=-1;c=getchar();}
    33     while( isdigit(c)){x=(x<<3)+(x<<1)+c-48;c=getchar();}
    34     return x*w;
    35 }
    36 int main(){
    37     T=ri();
    38     for(R int i=1;i<=T;++i){
    39         t++;
    40         for(R int i=1;i<=n*3+2;++i)G[i].clear();
    41         n=ri(),m=ri(),c=ri();
    42         for(R int i=1;i<=n;++i)num[i]=ri();
    43         for(R int i=1;i<=n;++i){
    44             int nm=num[i];
    45             edge e={i,c},ee={nm+n+1,0},eee={i,0},eeee={nm+2*n+1,c};
    46             G[nm+n].push_back(e);
    47             G[i].push_back(ee);
    48             G[nm+2*n+2].push_back(eee);
    49             G[i].push_back(eeee);
    50         }
    51         for(R int i=1;i<=m;++i){
    52             int u,v,w;
    53             u=ri(),v=ri(),w=ri();
    54             edge e={v,w},ee={u,w};
    55             G[u].push_back(e);
    56             G[v].push_back(ee);
    57         }
    58         dijkstra(1);
    59         printf("Case #%d: ",t);
    60         if(d[n]==INF)printf("-1
    ");
    61         else printf("%d
    ",d[n]);
    62     }
    63     return 0;
    64 }

    spfa:

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cmath>
     4 #include<queue>
     5 #include<cstring>
     6 #include<cstdlib>
     7 using namespace std;
     8 const int inf=2100000000;
     9 int ne,n,m,c;
    10 int T;
    11 bool vis[200004],use[200004];
    12 int dis[200004];
    13 int pos[200004];
    14 int ra[200004];
    15 struct data{
    16        int von,w,next;
    17 }e[4000004];
    18 void insert(int u,int v,int w){
    19      ++ne;
    20      e[ne].w=w;
    21      e[ne].von=v;
    22      e[ne].next=pos[u];
    23      pos[u]=ne;
    24 }
    25 queue<int>q;
    26 void spfa(){
    27     int w,u,v,i;
    28     while(!q.empty())q.pop();
    29     dis[1]=0; vis[1]=true; q.push(1);
    30     while(!q.empty()){
    31         u=q.front(); q.pop(); vis[u]=false; i=pos[u];
    32         while(i!=0){
    33             v=e[i].von;
    34             w=e[i].w;
    35             if(dis[v]>dis[u]+w){
    36                 dis[v]=dis[u]+w;
    37                 if(!vis[v]){vis[v]=true; q.push(v);}
    38             }
    39             i=e[i].next;    
    40         }                      
    41     }
    42 }
    43 int main(){
    44     scanf("%d",&T);
    45     for(int t=1;t<=T;t++){
    46         memset(dis,127/3,sizeof(dis));
    47         memset(vis,false,sizeof(vis));
    48         memset(pos,0,sizeof(pos));
    49         memset(use,false,sizeof(use));
    50         ne=0;
    51         scanf("%d%d%d",&n,&m,&c);
    52         for(int i=1;i<=n;i++){scanf("%d",&ra[i]); use[ra[i]]=true;}
    53         for(int i=1;i<n;i++){
    54             if(use[i+1]&&use[i])
    55                 insert(n+i+1,n+i,c),
    56                 insert(n+i,n+i+1,c);             
    57         }
    58         for(int i=1;i<=n;i++){
    59             insert(n+ra[i],i,0);
    60             if(ra[i]<n)insert(i,n+ra[i]+1,c);
    61             if(ra[i]>1)insert(i,n+ra[i]-1,c);
    62         }
    63         for(int i=1;i<=m;i++){
    64             int u,v,w;
    65             scanf("%d%d%d",&u,&v,&w);
    66             insert(u,v,w);insert(v,u,w);
    67         }
    68         spfa();
    69         if(dis[n]<inf)printf("Case #%d: %d
    ",t,dis[n]);
    70         else printf("Case #%d: %d
    ",t,-1);
    71     }
    72     return 0;
    73 }

    P1875 佳佳的魔法药水

    题目背景

    发完了 k 张照片,佳佳却得到了一个坏消息:他的 MM 得病了!佳佳和大家一样焦急 万分!治好 MM 的病只有一种办法,那就是传说中的 0 号药水 ……怎么样才能得到 0 号药 水呢?你要知道佳佳的家境也不是很好,成本得足够低才行……

    题目描述

    得到一种药水有两种方法:可以按照魔法书上的指导自己配置,也可以到魔法商店里去 买——那里对于每种药水都有供应,虽然有可能价格很贵。在魔法书上有很多这样的记载:

    1 份 A 药水混合 1 份 B 药水就可以得到 1 份 C 药水。(至于为什么 1+1=1,因为……这是魔 法世界)好了,现在你知道了需要得到某种药水,还知道所有可能涉及到的药水的价格以及 魔法书上所有的配置方法,现在要问的就是:1.最少花多少钱可以配制成功这种珍贵的药水;

    2.共有多少种不同的花费最少的方案(两种可行的配置方案如果有任何一个步骤不同则视为 不同的)。假定初始时你手中并没有任何可以用的药水。

    输入输出格式

    输入格式:

    第一行有一个整数 N(N<=1000),表示一共涉及到的药水总数。药水从 0~N­1 顺序编号,0 号药水就是 最终要配制的药水。

    第二行有 N 个整数,分别表示从 0~N­1 顺序编号的所有药水在魔法商店的价格(都表示 1 份的价格)。

    第三行开始,每行有 3 个整数 A、B、C,表示 1 份 A 药水混合 1 份 B 药水就可以得到 1 份 C 药水。注意,某两种特定的药水搭配如果能配成新药水的话,那么结果是唯一的。也就是 说不会出现某两行的 A、B 相同但 C 不同的情况。

    输入以一个空行结束。

    输出格式:

    输出两个用空格隔开的整数,分别表示得到 0 号药水的最小花费以及花费最少的方案的个 数。

    输入输出样例

    输入样例#1: 
    7 
    10 5 6 3 2 2 3 
    1 2 0 
    4 5 1 
    3 6 2
    
    输出样例#1: 
    10 3

    说明

    样例说明:

    最优方案有 3 种,分别是:直接买 0 号药水;买 4 号药水、5 号药水配制成 1 号药水,直接 买 2 号药水,然后配制成 0 号药水;买 4 号药水、5 号药水配制成 1 号药水,买 3 号药水、6 号药水配制成 2,然后配制成 0。

    既然把他标上了最短路的标签,那就不难想到以想象成连通图的方式,解决第一问。由于还要记录方案,不选择dijkstra。

    spfa:

     1 #include <iostream>
     2 #include <cstdio> 
     3 #define R register
     4 #define INF 0x7fffff
     5 #define MN 1005
     6 using namespace std;
     7 int n,d[MN],ans[MN],g[MN][MN];
     8 bool vis[MN];
     9 inline int ri(){
    10     char c=getchar();int x=0,w=1;
    11     while(!isdigit(c)){if(c=='-')w=-1;c=getchar();}
    12     while( isdigit(c)){x=(x<<3)+(x<<1)+c-48;c=getchar();}
    13     return x*w;
    14 }
    15 int main(){
    16     n=ri();
    17     for(R int i=1;i<=n;++i)d[i]=ri(),ans[i]=1;
    18     int u,v,w;
    19     while(scanf("%d%d%d",&u,&v,&w)==3)g[u+1][v+1]=g[v+1][u+1]=w+1;//+1变成习惯的储存方式
    20     for(R int i=1;i<n;++i){
    21         int tmp=INF;
    22         for(R int j=1;j<=n;++j)if(!vis[j]&&d[j]<tmp)tmp=d[j],v=j;
    23         vis[v]=1;
    24         for(R int j=1;j<=n;++j)if(vis[j]&&g[v][j]){
    25             if(d[v]+d[j]==d[g[v][j]])ans[g[v][j]]+=ans[v]*ans[j];
    26             if(d[v]+d[j]<d[g[v][j]])d[g[v][j]]=d[v]+d[j],ans[g[v][j]]=ans[v]*ans[j];
    27         }
    28     } 
    29     printf("%d %d",d[1],ans[1]);
    30     return 0;
    31 }

    P4610 [COCI2011-2012#7] KAMPANJA

    solution

    题目背景

    临近选举,总统要在城市111和城市222举行演讲。他乘汽车完成巡回演讲,从111出发,途中要经过城市222,最后必须回到城市111.特勤局对总统要经过的所有城市监控。为了使得费用最小,必须使得监控的城市最少。求最少要监控的城市。

    题目描述

    一共有NNN个城市,有MMM条有向边。(0<=N,M<=200)(0<=N,M<=200)(0<=N,M<=200) 有N从1出发途中要经过222,最后要回到1的路线中最少要经过的点的数目。

    输入输出格式

    输入格式:

    第一行包含222个整数N,MN,MN,M。NNN表示城市的数目,MMM表示有向边的数目。 接下来MMM行,每行两个数A,BA,BA,B,表示从AAA到BBB有一条有向边。

    输出格式:

    最少要监控的城市的数量。

    输入输出样例

    输入样例#1:
    6 7
    1 3
    3 4
    4 5
    5 1
    4 2
    2 6
    6 3
    输出样例#1:
    6

    说明

    0<=N,M<=2000<=N,M<=2000<=N,M<=200

    本题数据加强by Imagine

    CF95C Volleyball

  • 相关阅读:
    arcgis api 3.x for js 入门开发系列八聚合效果(附源码下载)
    arcgis api 3.x for js 入门开发系列七图层控制(附源码下载)
    arcgis api 3.x for js 入门开发系列六地图分屏对比(附源码下载)
    arcgis api 3.x for js 入门开发系列五地图态势标绘(附源码下载)
    arcgis api 3.x for js 入门开发系列四地图查询(附源码下载)
    Java里面获取当前服务器的IP地址
    Flutter at Google I/O 2018
    Modbus RTU 协议使用汇总
    plsql 创建表空间、用户、赋予权限
    Oracle:ODP.NET Managed 小试牛刀
  • 原文地址:https://www.cnblogs.com/flicker-five/p/10330351.html
Copyright © 2011-2022 走看看