PIPIOJ 1111: 最小花费

题目链接:
传送门

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

输入:
输入包含多组测试用例。
对于每组样例,第一行输入两个正整数n,m,分别表示总人数和可以互相转账的人的对数。(0<n<=2000)以下m行每行输入三个正整数x,y,z。表示标号为x的人和标号为y的人之间互相转账需要扣除z%的手续费(z<100)。
最后一行输入两个正整数A,B。数据保证A与B之间可以直接或间接地转账

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

样例输入:
3 3
1 2 1
2 3 2
1 3 3
1 3

样例输出:
103.07153164

题目思路:
期末考试的互联网反垄断那题的源头,dijkstra算法的变题。

dijkstra算法题解c参考代码:

#include <stdio.h>
#include <string.h>

#define MAX 2001

int n,m;
double map[MAX][MAX];
double dist[MAX];
int visited[MAX];

void dijkstra(int s,int e)
{
    
    
	memset(visited,0,sizeof(visited));
	int i,j;
	for(i=1;i<=n;i++)
	 dist[i]=map[s][i];
	
	dist[s]=1;
	visited[s]=1;
	
	for(i=1;i<n;i++)
	{
    
    
		double max=0;
		int pos;
		for(j=1;j<=n;j++)
		{
    
    
			if(visited[j]==0&&dist[j]>max)
			{
    
    
				max=dist[j];
				pos=j;
			}
		}
		
		if(pos==e)
		 break;
		else
		 visited[pos]=1;
		
		for(j=1;j<=n;j++)
		{
    
    
			if(visited[j]==0&&dist[j]<dist[pos]*map[pos][j])
			 dist[j]=dist[pos]*map[pos][j];
		}
	}
}

int main()
{
    
    
	int i,x,y,z,a,b;
	
	while(scanf("%d%d",&n,&m)!=EOF)
	{
    
    
		memset(map,0,sizeof(map));
		for(i=0;i<m;i++)
		{
    
    
			scanf("%d%d%d",&x,&y,&z);
			map[x][y]=map[y][x]=(double)(100-z)/100.0;
		}
		
	    scanf("%d%d",&a,&b);
	    
	    dijkstra(a,b);
	    
	    printf("%.8lf\n",100/dist[b]);
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_46139801/article/details/114751196