HDU 1879 继续畅通工程 (Prim(普里姆算法)+Kruskal(克鲁斯卡尔))

继续畅通工程

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 10765    Accepted Submission(s): 4704


Problem Description
省政府“畅通工程”的目标是使全省任何两个村庄间都可以实现公路交通(但不一定有直接的公路相连,只要能间接通过公路可达即可)。现得到城镇道路统计表,表中列出了任意两城镇间修建道路的费用,以及该道路是否已经修通的状态。现请你编写程序,计算出全省畅通需要的最低成本。
 

 

Input
测试输入包含若干测试用例。每个测试用例的第1行给出村庄数目N ( 1< N < 100 );随后的 N(N-1)/2 行对应村庄间道路的成本及修建状态,每行给4个正整数,分别是两个村庄的编号(从1编号到N),此两村庄间道路的成本,以及修建状态:1表示已建,0表示未建。

当N为0时输入结束。
 

 

Output
每个测试用例的输出占一行,输出全省畅通需要的最低成本。
 

 

Sample Input
3 1 2 1 0 1 3 2 0 2 3 4 0 3 1 2 1 0 1 3 2 0 2 3 4 1 3 1 2 1 0 1 3 2 1 2 3 4 1 0
 

 

Sample Output
3 1 0
 

 

Author
ZJU
 

 

Source
 

 

这道题虽然是一道模板题,但是有一点要注意:

不能使用  Scanner sc = new Scanner(new BufferedInputStream(System.in));  和

         System.out.println();

否则会超时;

推荐使用:  BufferedReader bu=new BufferedReader(new InputStreamReader(System.in));   和

                      PrintWriter pw=new PrintWriter(new OutputStreamWriter(System.out),true);

 

克鲁斯卡尔

 

import java.io.*;

import java.util.*;

public class Main {

	public  int n,m,sum;

	public  ArrayList<kr> ay=new ArrayList<kr>();;

	public  int pattern[];

	PrintWriter pw;

	public static void main(String[] args) throws IOException{

		new Main().work();

	}

	public void work() throws IOException{

		BufferedReader bu=new BufferedReader(new InputStreamReader(System.in));

		pw=new PrintWriter(new OutputStreamWriter(System.out),true);

		n=Integer.parseInt(bu.readLine());

		while(n!=0){

			m=(n*(n-1))>>1;

			ay.clear();

			sum=0;

			for(int i=0;i<m;i++){

				String str[]=bu.readLine().split(" ");

				int a=Integer.parseInt(str[0]);

				int b=Integer.parseInt(str[1]);

				int c=Integer.parseInt(str[2]);

				int d=Integer.parseInt(str[3]);

				if(d==1)

					c=0;

				kr k=new kr(a,b,c);

				ay.add(k);

			}

			Collections.sort(ay);

			Kruskral();

			pw.println(sum);

			n=Integer.parseInt(bu.readLine());

		}

	}

	public  void Kruskral(){

		pattern=new int[n+1];

		for(int i=1;i<=n;i++){

			pattern[i]=i;

		}

		for(int i=0;i<ay.size();i++){

			union(ay.get(i).a,ay.get(i).b,ay.get(i).c);

		}

	}

	public  void union(int a,int b,int c){

		int aa=find(a);

		int bb=find(b);

		if(aa==bb)

			return;

		if(aa>bb){

			pattern[bb]=aa;

			sum+=c;

			//pw.println(sum);

		}

		else{

			pattern[aa]=bb;

			sum+=c;

		}

	}

	public  int find(int x){

		int k,r,s;

		r=x;

		while(r!=pattern[r]){

			r=pattern[r];

		}

		k=x;

		while(k!=r){

			s=pattern[k];

			pattern[k]=r;

			k=s;

		}

		return r;

	}

}

class kr implements Comparable<kr>{

	int a;

	int b;

	int c;

	kr(int a,int b,int c){

		this.a=a;

		this.b=b;

		this.c=c;

	}

	public int compareTo(kr o) {

		return this.c>o.c?1:-1;

	}

}


 

 

普利姆算法

 

import java.io.*;

import java.util.*;



public class Main {

	public  int MAX=2000000;

	public  int map[][];

	public  int n,m;

	PrintWriter pw;

	public static void main(String args[]) throws IOException{

		new Main().work();

	}

	public  void work() throws IOException{

		//Scanner sc=new Scanner(new BufferedInputStream(System.in));

		BufferedReader bu=new BufferedReader(new InputStreamReader(System.in));

		pw=new PrintWriter(new OutputStreamWriter(System.out),true);

		n=Integer.parseInt(bu.readLine());

		while(n!=0){

			m=(n*(n-1))>>1;

			map=new int[n+1][n+1];

			for(int i=1;i<=n;i++){

				for(int j=1;j<=n;j++){

					map[i][j]=MAX;

				}

			}

			

			for(int i=1;i<=m;i++){

				String str[]=bu.readLine().split(" ");

				int a=Integer.parseInt(str[0]);

				int b=Integer.parseInt(str[1]);

				int c=Integer.parseInt(str[2]);

				int d=Integer.parseInt(str[3]);

				if(d==1){

					c=0;

				}

				if(map[a][b]>c)

					map[a][b]=map[b][a]=c;

			}

			getDistance();

			n=Integer.parseInt(bu.readLine());

		}

	}

	////Prim(普里姆算法)

	public  void getDistance(){

		int k=0,sum=0;

		int dis[]=new int[n+1];

		int mark[]=new int[n+1];

		for(int i=2;i<=n;i++){

			dis[i]=map[1][i];//初始化起点到其他点之间的距离

		}

		mark[1]=1;

		for(int i=1;i<n;i++){

			int min=MAX;

			// 每次循环寻找的最短的边

			for(int j=2;j<=n;j++){

				if(mark[j]==0&&dis[j]<min){

					min=dis[j];

					k=j;

				}

			}

			if(min==MAX) break;

			mark[k]=1;

			sum+=dis[k];

			//到一个新的点,从新计算到其他点之间的距离

			for(int j=2;j<=n;j++){

				if(mark[j]==0&&dis[j]>map[k][j])

					dis[j]=map[k][j];

			}

		}

			pw.println(sum);

	}

}


 

 

 

你可能感兴趣的:(Prim)