继续畅通工程
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时输入结束。
当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); } }