poj1860

涉及算法:BellMan-Ford
题目大意:给定几种货币和他们之间的交换关系,交换关系由汇率rab和手续费cab组成,举个例子若A-->B的交换关系为rab、cab,则用数量为v的货币A交换B可以得到的B的数量为:(v-cab)*rab。问s货币是否能够在若干次交换后数量增加
题目分析:建立模型:每种货币都是一个结点,结点A—>B之间的权值为:(v-cab)*rab,找一条从s结点可以到达且权值为正的环路,若存在则s货币的数量可以增加否则不能

public class Main_1860 {

	
	static int n,m,s;
	static double v;
	static Edge e[]=new Edge[201];
	static double dis[]=new double[101];//s到各个结点的权值
	static int x;
	
	static class Edge{
		
		int a;int b;double rab;double cab;//a-->b
		
	}
	
	public static void main(String[] args) {

		Scanner in=new Scanner(System.in);
		
		n=in.nextInt();
		m=in.nextInt();
		s=in.nextInt();//源结点
		v=in.nextDouble();
		
		x=1;
		int a,b;double r,c;
		for(int i=1;i<=m;i++){
			a=in.nextInt();
			b=in.nextInt();
			r=in.nextDouble();
			c=in.nextDouble();
			
			e[x]=new Edge();
			e[x].a=a;
			e[x].b=b;
			e[x].rab=r;
			e[x++].cab=c;
			
			r=in.nextDouble();
			c=in.nextDouble();
			
			e[x]=new Edge();
			e[x].a=b;
			e[x].b=a;
			e[x].rab=r;
			e[x++].cab=c;
			
		}
		
		if(bellmanFord()){
			System.out.println("YES");
		}else {
			System.out.println("NO");
		}

	}
	
	static boolean flag;
	static boolean bellmanFord(){
		
		dis[s]=v;//s到其余结点的权值可初始化为0;初始化的选取要能够使没有和s联通的的节点结点永远不会更新,且与s联通的结点的更新不会受到阻碍
		
		//进行n-1次松弛可以使源到所有结点达到最大值
		for(int i=1;i<n;i++){
			
			flag=false;
			for(int j=1;j<x;j++){
				if(dis[e[j].b]<(dis[e[j].a]-e[j].cab)*e[j].rab){
					dis[e[j].b]=(dis[e[j].a]-e[j].cab)*e[j].rab;
					flag=true;
				}
			}
			if(!flag) break;//第i次没有更新结点,则后面的每一次都可能更新结点了,所以这里可以跳出循环
		}
		
		//若其他节点到s存在正环,或者其他结点(那些s能到达的节点)之间存在正环,则s——>s能够增加
		//注意那些s不能到达的节点经过松弛操作后仍然为0
		for(int i=1;i<x;i++){
			if(dis[e[i].b]<(dis[e[i].a]-e[i].cab)*e[i].rab){//是否存在正环
				return true;
			}
		}
		
		
		return false;
	}
}


你可能感兴趣的:(Exchange,currency,acm1860)