时间限制:1 秒内存限制:128 兆特殊判题:否提交:341解决:96
题目描述:
已知一个无向带权图,求最小整数k。使仅使用权值小于等于k的边,节点1可以与节点n连通。
输入:
输入包含多组测试用例,每组测试用例的开头为一个整数n(1 <= n <= 10000),m(1 <= m <= 100000),代表该带权图的顶点个数,和边的个数。
接下去m行,描述图上边的信息,包括三个整数,a(1 <= a <= n),b(1 <= b <= n),c(1 <= c <= 1000000),表示连接顶点a和顶点b的无向边,其权值为c。
输出:
输出为一个整数k,若找不到一个整数满足条件,则输出-1。
样例输入:
3 3
1 3 5
1 2 3
2 3 2
3 2
1 2 3
2 3 5
3 1
1 2 3
样例输出:
3
5
-1
【解题思路】
其实这个题目乍一看,很复杂,没有思路。
仔细想想,就是选取一些边,但是这些边的长度要比k小。
其实基本思路还是使用并查集。
1、输入数据,保存在对象中。数据全部输入之后,需要对数据进行排序。条件是边的权值从小到大。
2、依次读取该对象的内容,合并。发现节点1和节点n已经在同一个集合中,就更新最小边,break。
3、输出结果。
Java超时了,过了三个案例。C++ AC了,其实就是一样的思路,换了一种语言而已。
Java TLE
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.StreamTokenizer;
import java.util.Arrays;
public class Main {
/*
* 1545
*/
private static int parent[];
public static void main(String[] args) throws IOException {
StreamTokenizer st = new StreamTokenizer(new BufferedReader(
new InputStreamReader(System.in)));
while (st.nextToken() != StreamTokenizer.TT_EOF) {
int n = (int)st.nval;
st.nextToken();
int m = (int)st.nval;
Node nodes[] = new Node[m];
for (int i = 0; i < m; i++) {
st.nextToken();
int start = (int)st.nval;
st.nextToken();
int end = (int)st.nval;
st.nextToken();
int value = (int)st.nval;
nodes[i] = new Node(start, end, value);
}
Arrays.sort(nodes);
parent = new int[n + 1];
for (int i = 1; i < n+1; i++) {
parent[i] = i;
}
int k = -1;
for (int i = 0; i < m; i++) {
union(nodes[i].start, nodes[i].end);
if (findParent(1) == findParent(n)) {
k = nodes[i].value;
break;
}
}
System.out.println(k);
}
}
private static void union(int f, int t) {
int a = findParent(f);
int b = findParent(t);
if (a == b)
return;
if (a > b) {
parent[a] = b;
} else {
parent[b] = a;
}
}
private static int findParent(int f) {
while (parent[f] != f) {
f = parent[f];
}
return f;
}
private static class Node implements Comparable<Node>{
private int start;
private int end;
private int value;
public Node(int start, int end, int value) {
super();
this.start = start;
this.end = end;
this.value = value;
}
public int compareTo(Node o) {
if (o.value < this.value) {
return 1;
}else {
return -1;
}
}
}
}
/**************************************************************
Problem: 1545
User: wzqwsrf
Language: Java
Result: Time Limit Exceed
****************************************************************/
C++ AC
#include<stdio.h>
#include<algorithm>
const int maxn = 10002;
const int maxm = 100002;
int parent[maxn];
using namespace std;
struct Node{
int start;
int end;
int value;
}nodes[maxm];
int compare(Node node1 ,Node node2){
if(node1.value < node2.value){
return 1;
}
return 0;
}
int findParent(int f) {
while (parent[f] != f) {
f = parent[f];
}
return f;
}
void unionTwo(int f, int t) {
int a = findParent(f);
int b = findParent(t);
if (a == b)
return;
if (a > b) {
parent[a] = b;
} else {
parent[b] = a;
}
}
int main(){
int n;
int m;
while(scanf("%d%d",&n,&m)!=EOF){
int i = 0;
for(i=0; i < m; i++){
scanf("%d%d%d" , &nodes[i].start, &nodes[i].end, &nodes[i].value);
}
sort(nodes,nodes+m,compare);
for(i = 1; i < n+1 ; i++){
parent[i] = i;
}
int k = -1;
for (i = 0; i < m; i++) {
unionTwo(nodes[i].start, nodes[i].end);
if (findParent(1) == findParent(n)) {
k = nodes[i].value;
break;
}
}
printf("%d\n",k);
}
return 0;
}
/**************************************************************
Problem: 1545
User: wzqwsrf
Language: C++
Result: Accepted
Time:670 ms
Memory:2232 kb
****************************************************************/