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

  • 相关阅读:
    web网站的测试需考虑的问题
    颜色搭配
    30岁前不必在乎的30件事情
    数据库时代的终结
    实现IT创业的十三种模式分析
    Linux rpm 命令参数使用详解[介绍和应用]
    PHP中的正则表达式及模式匹配
    linux下使用yum安装Apache+php+Mysql+phpMyAdmin
    jQuery.extend函数详细用法
    PHP CURL HTTP 研究笔记
  • 原文地址:https://www.cnblogs.com/flicker-five/p/10330351.html
Copyright © 2011-2022 走看看