Problem:
灯篭
会津若松市は「歴史の町」として知られています。今から約 400 年前、蒲生氏郷により城下町の骨格が作られましたが、その後、徳川三代将軍家光公の異母弟「保科正之」公を藩祖とする会津藩 23 万石の中心都市として発展しました。今でも市内のいたるところに史跡や昔日の面影が残っているため、毎年、全国から多くの観光客が訪れています。
今年は、ＮＨＫ大河ドラマで「新選組！」が放送されているため、新選組ゆかりの地(*1)として、大幅に観光客が増加しています。そこで市では、市内に点在する史跡を結ぶ通り沿いに 100 m 間隔で灯篭を設置して飾りたてることにしました。灯篭を飾ってある通りを辿れば市内の全ての史跡に到達できるように設置することが条件ですが、一筆書きでたどれる必要はありません。しかし、予算が限られているので設置する灯篭の数を最小限にする必要があります。
史跡と史跡を結ぶ通りのデータを読み込んで、必要最小限の灯篭の数を出力するプログラムを作成して下さい。ただし、史跡と史跡の間の距離は 200 m 以上で、100 の倍数で与えられます。おのおのの史跡から一番近い灯篭までの距離は 100 m で、市内の史跡は 100 箇所以内です。史跡自身には灯篭を設置する必要はありません。
(*1) 新選組は会津藩御預という形で発足、白虎隊の悲劇で知られる会津戊辰戦争に参戦、市内天寧寺に土方歳三が近藤勇の墓を建立
Input
複数のデータセットが与えられます。各データセットは以下の形式で与えられます。
n
m
a
1
,
b
1
,
d
1
a
2
,
b
2
,
d
2
:
a
m
,
b
m
,
d
m
各データセットの最初の 1 行には史跡の箇所数
n
が与えられます。続いて史跡と史跡を結ぶ通りの数
m
が与えられます。続く
m
行に カンマで区切られてた3 つの数数
a
i
,
b
i
,
d
i
が与えられます。
a
i
,
b
i
は史跡の番号です。史跡の番号は 0 番から
n
- 1 番まで振られています。
a
i
b
i
はそれらを結ぶ通りがあることを示し、
d
i
は
a
i
b
i
間の道路の距離を表します。
n
が 0 のとき入力の最後とします。データセットの数は 20 を超えません。
Output
各データセットに対して、必要最小限の灯篭の数を１行に出力して下さい。
Sample Input
4
4
0,1,1500
0,2,2000
1,2,600
1,3,500
0
Output for the Sample Input
23

Submitted solutions:

code_snippet: // 0072
#include <iostream>
#include <vector>
#include <stdio.h>
#include <stdlib.h>
using namespace std;

struct road{
	int dis;
	int v1;
	int v2;
};


int findSet(int x, vector<int> &p){
	if(x != p[x])
		p[x] = findSet(p[x], p);
	return p[x];
}

bool isSameSet(int x, int y, vector<int> &p){
	return findSet(x, p) == findSet(y, p);
}

void link(int x, int y, vector<int> &p, vector<int> &rank){
	if(rank[x] > rank[y]){
		p[y] = x;
	}else{
		p[x] = y;
		if(rank[x] == rank[y])
			rank[y]++;
	}
}

void unite(int x, int y, vector<int> &p, vector<int> &rank){
	link(findSet(x, p), findSet(y, p), p, rank);
}

void Sort(vector<road> &ver){
	road r;
	for(int i=0;i<ver.size();i++){
		for(int j=1;j<ver.size()-i;j++){
			if(ver[j-1].dis > ver[j].dis){
				r = ver[j-1];
				ver[j-1] = ver[j];
				ver[j] = r;
			}
		}
	}
}

int lantern(vector<road> ver){
	vector<int> rank, p;
	for(int i=0;i<ver.size();i++){
		p.push_back(i);
		rank.push_back(0);
	}

	int lan = 0;
	for(int i=0;i<ver.size();i++){
		if(!isSameSet(ver[i].v1, ver[i].v2, p)){
			lan += ver[i].dis/100-1;
			unite(ver[i].v1, ver[i].v2, p, rank);
		}
	}

	return lan;
}

int main(){
	while(1){
		int n, m, a, b, d;
		vector<road> ver;
		road v;

		cin>>n;
		if(n == 0)
			break;

		cin>>m;
		for(int i=0;i<m;i++){
			scanf("%d,%d,%d", &a, &b, &d);
			v.v1 = a;
			v.v2 = b;
			v.dis = d;
			ver.push_back(v);
		}

		Sort(ver);
		
		cout<<lantern(ver)<<endl;
	}
	return 0;
}
accuracy: 1
time_ms: 20
memory_kb: 1396
final_rank: 4

code_snippet: #include <iostream>
#include <vector>
#include <string>
#include <algorithm>
using namespace std;

int n, m;

const int INF = 1e+9;
const int MAX_V = 100;
int cost[MAX_V][MAX_V];
int mincost[MAX_V];
bool used[MAX_V];

int prim(){
	for(int i=0 ; i < n ; i++ ){
		mincost[i] = INF;
		used[i] = false;
	}
	mincost[0] = 0;
	int res = 0;
	
	while( true ){
		int v = -1;
		for(int u=0 ; u < n ; u++ ){
			if( !used[u] && (v == -1 || mincost[u] < mincost[v]) ){
				v = u;
			}
		}
		
		if(v == -1) break;
		used[v] = true;
		res += mincost[v];
		
		for(int u=0 ; u < n ; u++ ){
			mincost[u] = min( mincost[u] , cost[v][u] );
		}
	}
	return res;
}

// ?????????s?????????c???????????§??????????????????
vector<string> split_string(string s, char c){
	string str;
	vector<string> vs;
	s.push_back( c );
	
	for(int i=0 ; i < s.size() ; i++ ){
		if( s[i] == c ){
			if( !str.empty() ){
				vs.push_back( str );
				str.clear();
			}
		}else{
			str.push_back( s[i] );
		}
	}
	return vs;
}

// string???int?????????
int s_to_i(string s){
	int n=0;
	for(int i=0 ; i < s.size() ; i++ ){
		n *= 10;
		n += s[i] - '0';
	}
	return n;
}

int main(){
	while( cin >> n , n ){
		for(int u=0 ; u < n ; u++ ){
			for(int v=0 ; v < n ; v++ ){
				cost[u][v] = cost[v][u] = INF;
			}
		}
		
		cin >> m;
		cin.ignore();
		for(int i=0 ; i < m ; i++ ){
			string s;
			getline(cin,s);
			vector<string> vs = split_string( s , ',' );
			int u = s_to_i( vs[0] );
			int v = s_to_i( vs[1] );
			int c = (s_to_i( vs[2] ) - 100) / 100;
			cost[u][v] = cost[v][u] = c;
		}
		int ans = prim();
		cout << ans << endl;
	}
}
accuracy: 1
time_ms: 10
memory_kb: 1252
final_rank: 1

code_snippet: #include <iostream>
#include <vector>
using namespace std;

struct LINE {
	int a;
	int b;
	int d;
	bool use;
};

vector<int> getconnect(vector<LINE> &lines,int n)
{
	vector<int>	r;
	for(int i=0;i<lines.size();i++){
		if( lines[i].a != lines[i].b && (lines[i].a==n || lines[i].b==n) ){
			r.push_back(i);
		}
	}
	return r;
}

int main() {

	while(true){

	int n,m;
	cin >> n >> m;
	if( n==0) break;
	
	vector<LINE> lines;
	
	for(int i=0;i<m;i++){
		LINE l;
		char c;
		cin >> l.a >> c >> l.b >> c >> l.d;
		l.use=false;
		lines.push_back(l);
	}

	while( true ){

		int count=0;
		for(int i=0;i<n;i++){
			auto idxs=getconnect(lines,i);
			if( idxs.empty() ) continue;

			count++;
			
			int mini = idxs[0];
			int mind = lines[mini].d;
			for(int idx : idxs){
				if( lines[idx].d < mind ){
					mini = idx;
					mind = lines[idx].d;
				}
			}
			int t = lines[mini].a!=i?lines[mini].a:lines[mini].b;
			
			auto idxs2=getconnect(lines,t);
			for(int idx : idxs2){
				if( lines[idx].a==t){
					lines[idx].a = i;
				}
				if( lines[idx].b==t){
					lines[idx].b = i;
				}
			}

			lines[mini].use=true;
		}
		if( count==0) break;
		count=0;
	}

	int ans=0;
	for( auto l : lines){
		if( l.use){
			ans += l.d/100-1;
		}
	}
	cout << ans << endl;

	}
	return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 1348
final_rank: 2

code_snippet: // 2014/09/22 Tazoe

#include <iostream>
#include <string>
#include <sstream>
#include <algorithm>
using namespace std;

const int INF = 1000000000;

int main()
{
	while(true){
		int n;
		cin >> n;

		if(n==0)
			break;

		int W[100][100];
		for(int i=0; i<n; i++){
			for(int j=0; j<n; j++){
				W[i][j] = INF;
			}
		}

		int m;
		cin >> m;

		for(int i=0; i<m; i++){
			string s;
			cin >> s;

			for(int j=0; j<s.size(); j++){
				if(s[j]==','){
					s[j] = ' ';
				}
			}

			istringstream is(s);
			int a, b, d;
			is >> a >> b >> d;

			W[a][b] = W[b][a] = d;
		}
/*
		for(int i=0; i<n; i++){
			for(int j=0; j<n; j++){
				if(W[i][j]==INF){
					cout << "INF" << ' ';
				}
				else{
					cout << W[i][j] << ' ';
				}
			}
			cout << endl;
		}
*/

		int mincost[100];
		bool used[100];

		for(int i=0; i<n; i++){
			mincost[i] = INF;
			used[i] = false;
		}

		mincost[0] = 0;
		int res = 0;

		while(true){
			int v = -1;
			for(int u=0; u<n; u++){
				if(!used[u] && (v==-1 || mincost[u]<mincost[v])){
					v = u;
				}
			}

			if(v==-1)
				break;

			used[v] = true;
			if(v!=0){
				res += (mincost[v]/100-1);
			}

			for(int u=0; u<n; u++){
				mincost[u] = min(mincost[u], W[v][u]);
			}
		}

		cout << res << endl;
	}

	return 0;
}
accuracy: 1
time_ms: 20
memory_kb: 1256
final_rank: 3