洛谷 P1756 最小花费

Posted り挽歌、花开花落的流年

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了洛谷 P1756 最小花费相关的知识,希望对你有一定的参考价值。

题目背景

题目描述

在n个人中,某些人的银行账号之间可以互相转账。这些人之间转账的手续费各不相同。给定这些人之间转账时需要从转账金额里扣除百分之几的手续费,请问A最少需要多少钱使得转账后B收到100元。

输入输出格式

输入格式:

第一行输入两个正整数n,m,分别表示总人数和可以互相转账的人的对数。

以下m行每行输入三个正整数x,y,z,表示标号为x的人和标号为y的人之间互相转账需要扣除z%的手续费 (z<100)。

最后一行输入两个正整数A,B。数据保证A与B之间可以直接或间接地转账。

输出格式:

输出A使得B到账100元最少需要的总费用。精确到小数点后8位。

输入输出样例

输入样例#1:
3 3                                     
1 2 1
2 3 2
1 3 3
1 3
输出样例#1:
103.07153164

说明

1<=n<=2000

AC代码:

N^2都能过,无语。。

 1 #include<iostream>
 2 #include<cstdio>
 3 #define MAXN 2001
 4 #define inf 99999
 5 using namespace std;
 6 int N,M,A,B;
 7 double m[MAXN][MAXN];
 8 int main()
 9 {
10     int i,j;
11     cin>>N>>M;
12     cout.setf(ios::fixed);
13     for (i=0;i<N;i++)
14         for (j=0;j<N;j++)
15             m[i][j]=1/inf;// 就这样来看是0
16     
17     for (i=0;i<M;i++)
18     {
19         int x,y,t;
20         cin>>x>>y>>t;
21         x--; y--;
22         m[x][y]=m[y][x]=1-(t/100.0);//转换成剩余百分之多少
23     }
24    
25     cin>>A>>B;
26     A--; B--;
27     //dijkstra
28     double dis[MAXN];                            //dis i:money needed to trans 100 to i
29     bool book[MAXN];
30     book[B]=true;
31     for (i=0;i<N;i++)
32     {
33         dis[i]=100/m[B][i];                    //init dis[]
34         book[i]=false;                            //init book[]
35     }
36     for (j=0;j<N;j++)
37     {
38         int nmin;
39         double min=inf;
40         for (i=0;i<N;i++)
41             if (dis[i]<min&&!book[i])
42             {
43                 nmin=i;
44                 min=dis[nmin];                    //find #min->nmin
45             }
46         book[nmin]=true;                        //record in book[]
47         for (i=0;i<N;i++)
48             if (min/m[nmin][i]<dis[i]&&!book[i])        //relax
49                 dis[i]=min/m[nmin][i];
50     }
51     printf("%.8lf",dis[A]);
52     return 0;
53 }

 

80分代码存档:

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<queue>
 5 #define N 2005
 6 using namespace std;
 7 int n,m,S,E,head[N],ei;
 8 double dis[N];
 9 bool exist[N];
10 struct node{
11     int u,v,next;
12     double w;
13 }e[N*25];
14 void add_edge(int u,int v,int x){
15     double w=(double)x;w/=100;
16     e[++ei].u=u;e[ei].v=v;e[ei].w=w;
17     e[ei].next=head[u];head[u]=ei;
18 }
19 queue<int> q;
20 void SPFA(){
21     for(int i=1;i<=n;i++) dis[i]=99999999.0;
22     memset(exist,false,sizeof(exist));
23     exist[S]=true;q.push(S);dis[S]=100.0;
24     while(!q.empty()){
25         int p=q.front();q.pop();
26         exist[p]=false;
27         for(int i=head[p];i;i=e[i].next){
28             int v=e[i].v;
29             if(dis[v]>dis[p]/(e[i].w)){
30                 dis[v]=dis[p]/(e[i].w);
31                 if(!exist[v]){
32                     q.push(v);exist[v]=true;
33                 }
34             }
35         }
36     }
37 }
38 int main()
39 {
40     scanf("%d%d",&n,&m);
41     for(int i=1,u,v,w;i<=m;i++){
42         scanf("%d%d%d",&u,&v,&w);
43         add_edge(v,u,100-w);
44         add_edge(u,v,100-w);
45     }
46     scanf("%d%d",&E,&S);
47     SPFA();
48     printf("%.8lf",dis[E]);
49     return 0;
50 }

刚开始用100往回乘(1+e[i].w)全错了,后来改成除了。。

思路:建立无向图(刚开始建成有向图了。。),跑最短路。。

 

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<queue>
 5 using namespace std;
 6 int n,m,S,E,head[15000],ei;
 7 double dis[2100];
 8 bool exist[2010];
 9 struct node{
10     int u,v,next;
11     double w;
12 }e[20000];
13 void add_edge(int u,int v,int x){
14     double w=(double)x;w/=100.0;
15     e[++ei].u=u;e[ei].v=v;e[ei].w=w;
16     e[ei].next=head[u];head[u]=ei;
17 }
18 queue<int> q;
19 void SPFA(){
20     for(int i=1;i<=n;i++) dis[i]=99999999.0;
21     memset(exist,false,sizeof(exist));
22     exist[S]=true;q.push(S);dis[S]=100.0;
23     while(!q.empty()){
24         int p=q.front();q.pop();
25         exist[p]=false;
26         for(int i=head[p];i;i=e[i].next){
27             int v=e[i].v;
28             if(dis[v]>dis[p]*(1.0+e[i].w)){
29                 dis[v]=dis[p]*(1.0+e[i].w);
30                 if(!exist[v]){
31                     q.push(v);exist[v]=true;
32                 }
33             }
34         }
35     }
36 }
37 int main()
38 {
39     scanf("%d%d",&n,&m);
40     for(int i=1,u,v,w;i<=m;i++){
41         scanf("%d%d%d",&u,&v,&w);
42         add_edge(v,u,w);
43         add_edge(u,v,w);
44     }
45     scanf("%d%d",&E,&S);
46     SPFA();
47     printf("%.8lf",dis[E]);
48     return 0;
49 }

这样写不知道为什么结果总是整数部分正确,小数部分全是0,一时没看出哪里错了

以上是关于洛谷 P1756 最小花费的主要内容,如果未能解决你的问题,请参考以下文章

洛谷 P1576 最小花费

洛谷 P1576 最小花费 dijkstar

洛谷 P3049 Landscaping ( 贪心 || DP)

救命(洛谷 U4525)

洛谷P1027 Car的旅行路线 计算几何 图论最短路

洛谷 [P3973] 线性代数