#include<stdio.h>#include<algorithm>
using namespace std;
const int maxn=100010;
int set[maxn];
int mark[maxn];
int flag;
int dis[maxn];
struct node{
int a,b,l;};node dot[maxn];
bool cmp(node a,node b){return a.l<b.l;}
int find(int x){return set[x]==x?set[x]:set[x]=find(set[x]);}
void merge(int x,int y){
int fx=find(x);
int fy=find(y);
if(fx!=fy)
set[fy]=fx;}
int main(){
int n,m;
while(scanf("%d %d",&n,&m)!=EOF&&n){
int len=0;
int count=0;
for(int i=0;i<maxn;i++)
set[i]=i;
for(int i=0;i<n;i++){
scanf("%d %d %d",&dot[i].a,&dot[i].b,&dot[i].l);}
sort(dot,dot+n,cmp);
for(int i=0;i<n;i++){
if(find(dot[i].a)!=find(dot[i].b)){
merge(dot[i].a,dot[i].b);len+=dot[i].l;
count++;}}
if(count==m-1)
printf("%d\n",len);else
printf("?\n");}return0;}
#include<stdio.h>#include<algorithm>#include <cmath>
using namespace std;
const int maxn=100010;
int set[maxn];
int mark[maxn];
int flag;
int dis[maxn];
int a[maxn];
int b[maxn];
struct node{
int a,b;
double l;};node dot[maxn];
bool cmp(node a,node b){return a.l<b.l;}
int find(int x){return set[x]==x?set[x]:set[x]=find(set[x]);}
void merge(int x,int y){
int fx=find(x);
int fy=find(y);
if(fx!=fy)
set[fy]=fx;}
int main(){
int n,m,t,s;
scanf("%d",&t);
while(t--){
scanf("%d",&n);s=0;
double len=0;
int count=0;
for(int i=0;i<maxn;i++)
set[i]=i;
for(int i=0;i<n;i++){
scanf("%d %d",&a[i],&b[i]);}
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
double k=sqrt((a[i]-a[j])*(a[i]-a[j])+(b[i]-b[j])*(b[i]-b[j])*1.0);
if(k>=10&&k<=1000){
dot[s].a=i;
dot[s].b=j;
dot[s++].l=k;
}
}
}
sort(dot,dot+s,cmp);
for(int i=0;i<s;i++)
{
if(find(dot[i].a)!=find(dot[i].b)){
merge(dot[i].a,dot[i].b);len+=dot[i].l;
count++;}}
if(count==n-1)
printf("%.1f\n",len*100);else
printf("oh!\n");}return0;}
kruskal
#include<bits/stdc++.h>
using namespace std;
const int maxn =110;
struct Edge{
int u, v, w;
bool operator <(const Edge &r)const{ //边权从小到大排序
return w < r.w;}}E[maxn * maxn];
int n, m, f[maxn];
int find(int x){return x == f[x] ? x : f[x]= find(f[x]);}
void Kruskal(int n, int m){
int res =0; // 存放结果
int num =0; // 记录当前选择了多少条边
sort(E + 1, E + 1 + m);
for(int i =1; i <= n; i++) f[i]= i; //初始化 每个点自己为一个集合
for(int i =1; i <= m; i++){
int f1 = find(E[i].u); // 查询u顶点在哪个集合中
int f2 = find(E[i].v); // 查询v顶点在哪个集合中
if(f1 != f2){ // 如果不在同一个集合中
num++; // 选中的边数 +1
res += E[i].w; // 答案加上这条边的权值
f[f1]= f2; // 将这两个点合并到一个集合中
}
if(num == n - 1) // 如果已经找到了 n - 1条边,说明最小生成树已经构建完成了
break;}
if(num == n - 1) printf("%d\n", res);else puts("?");}
int main(){
while(~scanf("%d %d", &m, &n)){
if(m ==0)break;
for(int i =1; i <= m; i++)
scanf("%d%d%d", &E[i].u, &E[i].v, &E[i].w);
Kruskal(n, m);}return0;}
例题
#include<stdio.h>#include<algorithm>#include <cmath>
using namespace std;
const int maxn=100010;
int set[maxn];
int mark[maxn];
int flag;
int dis[maxn];
int a[maxn];
int b[maxn];
struct node{
int a,b;
int l;};node dot[maxn];
bool cmp(node a,node b){return a.l<b.l;}
int find(int x){return set[x]==x?set[x]:set[x]=find(set[x]);}
void merge(int x,int y){
int fx=find(x);
int fy=find(y);
if(fx!=fy)
set[fy]=fx;}
int main(){
int n,m,t,s,k;
while(scanf("%d",&n)&&n){s=0;
int len=0;
int count=0;
for(int i=0;i<maxn;i++)
set[i]=i;
for(int i=0;i<n*(n-1)/2;i++){
scanf("%d %d %d %d",&dot[i].a,&dot[i].b,&dot[i].l,&k);
if(k==1){
dot[i].l=0;}}
sort(dot,dot+n*(n-1)/2,cmp);
for(int i=0;i<n*(n-1)/2;i++){
if(find(dot[i].a)!=find(dot[i].b)){
merge(dot[i].a,dot[i].b);len+=dot[i].l;
count++;}}
printf("%d\n",len);}return0;}
#include<stdio.h>#include<algorithm>#include<iostream>#include <cmath>
using namespace std;
const int maxn=100010;
int set[maxn];
int mark[maxn];
int flag;
int dis[maxn];
int a[maxn];
int b[maxn];
struct node{
int a,b;
int l;};node dot[maxn];
bool cmp(node a,node b){return a.l<b.l;}
int find(int x){return set[x]==x?set[x]:set[x]=find(set[x]);}
void merge(int x,int y){
int fx=find(x);
int fy=find(y);
if(fx!=fy)
set[fy]=fx;}
int main(){
int n,t,s;
char k,m;
while(scanf("%d",&n)!=EOF){
if(n==0)break;s=0;
n--;
int len=0;
int count=0;
for(int i=0;i<maxn;i++)
set[i]=i;
getchar();
for(int i=0;i<n;i++){
cin>>k>>t;
while(t--){
cin>>m>>dot[s].l;
dot[s].b=m-'A';
dot[s++].a=k-'A';}}
sort(dot,dot+s,cmp);
for(int i=0;i<s;i++){
if(find(dot[i].a)!=find(dot[i].b)){
merge(dot[i].a,dot[i].b);len+=dot[i].l;
count++;}}
printf("%d\n",len);}return0;}
判断是否多解
#include<stdio.h>#include<algorithm>#include <cmath>
using namespace std;
const int maxn=100010;
int set[maxn];
int mark[maxn];
int flag;
int dis[maxn];
int a[maxn];
int b[maxn];
struct node{
int a,b;
int l;};node dot[maxn];
bool cmp(node a,node b){return a.l<b.l;}
int find(int x){return set[x]==x?set[x]:set[x]=find(set[x]);}
void merge(int x,int y){
int fx=find(x);
int fy=find(y);
if(fx!=fy)
set[fy]=fx;}
int main(){
int n,m,t,s,k;
scanf("%d",&t);
while(t--){
scanf("%d%d",&n,&m);s=0;
int len=0;
int count=0;
for(int i=0;i<maxn;i++)
set[i]=i;
for(int i=0;i<m;i++){
scanf("%d %d %d",&dot[i].a,&dot[i].b,&dot[i].l);}
sort(dot,dot+m,cmp);
for(int i=0;i<m;i++){
if(find(dot[i].a)!=find(dot[i].b)){
if(dot[i+1].l==dot[i].l){if((dot[i+1].a==dot[i].a&&dot[i+1].b!=dot[i].b)||(dot[i+1].a==dot[i].b&&dot[i+1].b!=dot[i].a)||(dot[i+1].b==dot[i].a&&dot[i+1].a!=dot[i].b)||(dot[i+1].b==dot[i].b&&dot[i+1].a!=dot[i].a)){
if(find(dot[i+1].a!=find(dot[i+1].b)))
count++;}}
merge(dot[i].a,dot[i].b);len+=dot[i].l;}}
if(count==0)
printf("%d\n",len);else
printf("Not Unique!\n");}return0;}
最大生成树
#include<stdio.h>#include<algorithm>#include <cmath>
using namespace std;
const int maxn=100010;
int set[maxn];
int mark[maxn];
int flag;
int dis[maxn];
int a[maxn];
int b[maxn];
struct node{
int a,b;
int l;};node dot[maxn];
bool cmp(node a,node b){return a.l>b.l;}
int find(int x){return set[x]==x?set[x]:set[x]=find(set[x]);}
void merge(int x,int y){
int fx=find(x);
int fy=find(y);
if(fx!=fy)
set[fy]=fx;}
int main(){
int n,m,t,s,k;
scanf("%d%d",&n,&m);s=0;
int len=0;
int count=0;
for(int i=0;i<maxn;i++)
set[i]=i;
for(int i=0;i<m;i++){
scanf("%d %d %d",&dot[i].a,&dot[i].b,&dot[i].l);}
sort(dot,dot+m,cmp);
for(int i=0;i<m;i++){
if(find(dot[i].a)!=find(dot[i].b)){
merge(dot[i].a,dot[i].b);len+=dot[i].l;
count++;}}
if(count==n-1)
printf("%d\n",len);else
printf("-1\n");return0;}
bfs搜索+最小生成树
#include<iostream>#include<string>
using namespace std;
const int inf=2501; //无限大,最大迷宫的总长也就2500
char map[51][51]; //迷宫原图
int node[51][51]; //记录当前格是否为字母,是第几个字母
int col,row; //当前迷宫的行列数
int num; //字母顶点数数目
int dist[102][102]; //构造结点图的两结点间权值,理论结点数最多为2500个(每一个允许通行的格为一个结点)
//但是POJ的数据库允许压缩到101个,哈哈,这样时间和空间复杂度都减少很多
int edge[102][102]; //构造字母图的两个字母间的边权,字母数最多为101
class move
{
public:
int row,col;}mov[4]={{0,-1},{0,1},{-1,0},{1,0}}; //分别对应 上 下 左 右
void bfs(int i,int j){
bool vist[51][51]; //标记当前迷宫某一格是否已被访问
int que_x[2500],que_y[2500]; //坐标队列
int head=0,tail=0; //队列指针
/*Initial*/
memset(dist,0,sizeof(dist));
memset(vist,false,sizeof(vist));
vist[i][j]=true;
que_x[tail]=i;
que_y[tail++]=j;
while(head<tail){
int x=que_x[head];
int y=que_y[head++];
if(node[x][y])
edge[ node[i][j]][ node[x][y]]= dist[x][y]; //抽取字母到字母的边权
for(int k=0;k<4;k++){
int mx=x+mov[k].row;
int my=y+mov[k].col;
if(mx>=1&& mx<= row && my>=1&& my<=col)
if(!vist[mx][my]&& map[mx][my]!='#'){
que_x[tail]=mx;
que_y[tail++]=my;
vist[mx][my]=true;
dist[mx][my]=dist[x][y]+1;}}}return;}
int prim(void){
int s=1;
int m=1;
bool u[102];
u[s]=true;
int min_w;
int prim_w=0;
int point;
int low_dis[102];
for(int i=1;i<=num;i++){
low_dis[i]=inf;
u[i]=false;}
while(true){
if(m==num)break;min_w=inf;
for(int i=2;i<=num;i++){
if(!u[i]&& low_dis[i]>edge[s][i])
low_dis[i]= edge[s][i];
if(!u[i]&& min_w>low_dis[i]){min_w=low_dis[i];point=i;}}s=point;
u[s]=true;prim_w+=min_w;
m++;}return prim_w;}
int main(int i,int j){
int test;
cin>>test;
while(test--){
/*Initial*/
memset(node,0,sizeof(node));num=0;
/*Input*/
cin>>col>>row;
char temp[51];
gets(temp); //吃掉cin遗留下来的换行符,我不知道为什么getchar()会AW
for(i=1;i<=row;i++){
gets(map[i]);
for(j=1;j<=col;j++)
if(map[i][j]=='A'||map[i][j]=='S')
node[i][j]=++num;}
/*BFS-> Structure Maps*/
for(i=1;i<=row;i++)
for(j=1;j<=col;j++)
if(node[i][j])
bfs(i,j); //构造结点i,j到其他所有结点的边权(非#的格子就是一个结点)
/*Prim Algorithm & Output*/
cout<<prim()<<endl;}return0;}