F - Truck History
建图:每两个字符串之间的相同位置不同字符的个数
prim
#include<stdio.h>
#include<iostream>
#include<string.h>
#define INF 0x3f3f3f3f
using namespace std;
/*
* 数组tree[]用来记录最小生成树的节点
* 数组lowdis[]记录从起点到其余所有点的距离并不断更新
* 数组map[][]记录所有数据两点之间的距离
* n是所有节点的数目,begin_1是起点
* Mindis是最小生成树的长度
主函数中输入前需要:
for(int i=1; i<=n; i++)
{
for(int j=1; j<=n; j++)
if(i==j) a[i][j]=0;
else a[i][j]=INF;
}
*/
const int N = 2000+10;
int tree[N];
int b[N];
int lowdis[N];
int a[N][N];
int n;
int begin_1;
void prime()
{
int i,j,Min,Mindis=0,next;
memset(tree,0,sizeof(tree));
for(i=1;i<=n;i++)
{
lowdis[i]=a[begin_1][i];//用lowdis[]数组记录下从起点到剩下所有点的距离
}
tree[begin_1]=1;//标记起点(即最小生成树中的点)
for(i=1;i<n;i++)
{
Min=INF;
for(j=1;j<=n;j++)
{
if(!tree[j]&&Min>lowdis[j])
{
Min=lowdis[j];//求出从当前起点到其余所有点的距离中最短的
next=j;
}
}
Mindis+=Min;//记录下整条最小树的长度
tree[next]=1;
for(j=1;j<=n;j++)
{
if(!tree[j]&&lowdis[j]>a[next][j])
lowdis[j]=a[next][j];//更新lowdis[]数组
}
}
printf("The highest possible quality is 1/%d.\n",Mindis);
}
void init(){
for(int i=1; i<=n; i++){
for(int j=1; j<=n; j++)
if(i==j) a[i][j]=0;
else a[i][j]=INF;
}
}
int main(){
int i,j,k,t;
char str[N][100];
while(~ scanf("%d",&n))
{
init();
if(n == 0)
break;
for(i = 1;i<=n;i ++)
{
scanf("%s",str[i]);
for(j = 1;j<=i;j ++)
{
t = 0;
for(k = 0;k<7;k ++)
{
if(str[i][k]!=str[j][k])
t ++;
a[i][j] = a[j][i] = t;
}
}
}
begin_1 = 1;
prime();
}
return 0;
}
求最小生成树第K大(小)边的题目。
prim 中的lowdis【】数组对应输出就可以了
#include<stdio.h>
#include<iostream>
#include<string.h>
#define INF 0x3f3f3f3f
#include<math.h>
#include<algorithm>
using namespace std;
/*
* 数组tree[]用来记录最小生成树的节点
* 数组lowdis[]记录从起点到其余所有点的距离并不断更新
* 数组map[][]记录所有数据两点之间的距离
* n是所有节点的数目,begin_1是起点
* Mindis是最小生成树的长度
主函数中输入前需要:
for(int i=1; i<=n; i++)
{
for(int j=1; j<=n; j++)
if(i==j) map_1[i][j]=0;
else map_1[i][j]=INF;
}
*/
const int N = 500+10;
int tree[N];
double lowdis[N];
double map_1[N][N];
int n,m;
int begin_1;
int k;
void prime()
{
int i,j,next;
double Min,Mindis = 0;
memset(tree,0,sizeof(tree));
for(i=1;i<=n;i++)
{
lowdis[i]=map_1[begin_1][i];//用lowdis[]数组记录下从起点到剩下所有点的距离
}
tree[begin_1]=1;//标记起点(即最小生成树中的点)
for(i=1;i<n;i++)
{
Min=INF;
for(j=1;j<=n;j++)
{
if(!tree[j]&&Min>lowdis[j])
{
Min=lowdis[j];//求出从当前起点到其余所有点的距离中最短的
next=j;
}
}
Mindis+=Min;//记录下整条最小树的长度
tree[next]=1;
for(j=1;j<=n;j++)
{
if(!tree[j]&&lowdis[j]>map_1[next][j])
lowdis[j]=map_1[next][j];//更新lowdis[]数组
}
}
sort(lowdis+1,lowdis+1+n);
printf("%.2f\n",lowdis[n-k+1]);
}
void init(){
for(int i=1; i<=n; i++){
for(int j=1; j<=n; j++)
if(i==j) map_1[i][j]=0;
else map_1[i][j]=INF;
}
}
struct node{
double x,y;
}t1[N];
int main(){
int t;
cin>>t;
while(t --)
{
cin>>k>>n;
init();
for(int i=1; i<=n; i++){
cin>>t1[i].x>>t1[i].y;
}
for(int i=1; i<=n; i++)
{
for(int j=1; j<i; j++)
{
double xx = sqrt((t1[i].x-t1[j].x)*(t1[i].x-t1[j].x)+(t1[i].y-t1[j].y)*(t1[i].y-t1[j].y));
map_1[i][j] = map_1[j][i] = xx;
}
}
begin_1 = 1;
prime();
}
return 0;
}
H - Highways
输出建边的路径
lowdis加个标记记录下,输出就可以了,加个fa【】数组同理,,v表示他的父亲节点是什么
#include<stdio.h>
#include<iostream>
#include<string.h>
#define INF 0x3f3f3f3f
#include<math.h>
#include<algorithm>
using namespace std;
/*
* 数组tree[]用来记录最小生成树的节点
* 数组lowdis[]记录从起点到其余所有点的距离并不断更新
* 数组map[][]记录所有数据两点之间的距离
* n是所有节点的数目,begin_1是起点
* Mindis是最小生成树的长度
主函数中输入前需要:
for(int i=1; i<=n; i++)
{
for(int j=1; j<=n; j++)
if(i==j) map_1[i][j]=0;
else map_1[i][j]=INF;
}
*/
const int N = 2000+10;
int tree[N];
//double lowdis[N];
double map_1[N][N];
int n,m;
int begin_1;
int k;
struct node{
double len;
int v;
}lowdis[N];
void prime()
{
int i,j,next;
double Min,Mindis = 0;
memset(tree,0,sizeof(tree));
for(i=1;i<=n;i++)
{
lowdis[i].v = 1;
lowdis[i].len=map_1[begin_1][i];//用lowdis[]数组记录下从起点到剩下所有点的距离
}
tree[begin_1]=1;//标记起点(即最小生成树中的点)
int cnt = 0;
for(i=1;i<n;i++)
{
Min=INF;
for(j=1;j<=n;j++)
{
if(!tree[j]&&Min>lowdis[j].len)
{
Min=lowdis[j].len;//求出从当前起点到其余所有点的距离中最短的
next=j;
}
}
Mindis+=Min;//记录下整条最小树的长度
tree[next]=1;
for(j=1;j<=n;j++)
{
if(!tree[j]&&lowdis[j].len>map_1[next][j])
{
lowdis[j].len=map_1[next][j];//更新lowdis[]数组
lowdis[j].v = next;
}
}
}
for(int i=1; i<=n; i++)
{
if(lowdis[i].len>0)
printf("%d %d\n",i,lowdis[i].v);
}
}
//void init(){
// for(int i=1; i<=n; i++){
// for(int j=1; j<=n; j++)
// if(i==j) map_1[i][j]=0;
// else map_1[i][j]=INF;
// }
//}
struct node1{
double x,y;
}t1[N];
int main(){
scanf("%d",&n);
{
// init();
for(int i=1; i<=n; i++){
scanf("%lf%lf",&t1[i].x,&t1[i].y);
}
for(int i=1; i<=n; i++)
{
for(int j=1; j<i; j++)
{
double xx = sqrt((t1[i].x-t1[j].x)*(t1[i].x-t1[j].x)+(t1[i].y-t1[j].y)*(t1[i].y-t1[j].y));
map_1[i][j] = map_1[j][i] = xx;
}
}
int m;
scanf("%d",&m);
while(m --)
{
int x,y;
scanf("%d%d",&x,&y);
map_1[x][y] = map_1[y][x] = -1;
}
begin_1 = 1;
prime();
}
return 0;
}
I - Agri-Net
模板,,直接套就可以了
#include<stdio.h>
#include<iostream>
#include<string.h>
#define INF 0x3f3f3f3f
using namespace std;
/*
* 数组tree[]用来记录最小生成树的节点
* 数组lowdis[]记录从起点到其余所有点的距离并不断更新
* 数组map[][]记录所有数据两点之间的距离
* n是所有节点的数目,begin_1是起点
* Mindis是最小生成树的长度
主函数中输入前需要:
for(int i=1; i<=n; i++)
{
for(int j=1; j<=n; j++)
if(i==j) map_1[i][j]=0;
else map_1[i][j]=INF;
}
*/
const int N = 1000+10;
int tree[N];
int lowdis[N];
int map_1[N][N];
int n;
int begin_1;
void prime()
{
int i,j,Min,Mindis=0,next;
memset(tree,0,sizeof(tree));
for(i=1;i<=n;i++)
{
lowdis[i]=map_1[begin_1][i];//用lowdis[]数组记录下从起点到剩下所有点的距离
}
tree[begin_1]=1;//标记起点(即最小生成树中的点)
for(i=1;i<n;i++)
{
Min=INF;
for(j=1;j<=n;j++)
{
if(!tree[j]&&Min>lowdis[j])
{
Min=lowdis[j];//求出从当前起点到其余所有点的距离中最短的
next=j;
}
}
Mindis+=Min;//记录下整条最小树的长度
tree[next]=1;
for(j=1;j<=n;j++)
{
if(!tree[j]&&lowdis[j]>map_1[next][j])
lowdis[j]=map_1[next][j];//更新lowdis[]数组
}
}
printf("%d\n",Mindis);
}
void init(){
for(int i=1; i<=n; i++){
for(int j=1; j<=n; j++)
if(i==j) map_1[i][j]=0;
else map_1[i][j]=INF;
}
}
int main(){
while(cin>>n && n)
{
init();
for(int i=1; i<=n; i++){
for(int j=1; j<=n; j++)
{
scanf("%d",&map_1[i][j]);
}
}
begin_1 = 1;
prime();
}
return 0;
}
最小生成树+BFS
题意:n*m的矩阵,空格代表可以走,#表示墙,A和S代表其中的点
建图:把图中各个字母之间的BFS的路径值存为边权值,
bfs,,坑,,
vj交不了,去poj交的
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <bitset>
#include <queue>
#include <set>
#include <map>
#include <string>
#include <algorithm>
using namespace std;
#define mem(a,b) memset(a,(b),sizeof(a))
#define CL(a, b) memset(a, b, sizeof(a))
#define debug(x) cout<<"debug"<<x<<"\n"
#define sc scanf
#define pr printf
#define INF 0x3f3f3f3f
#define PI acos(-1.0)
#define ll long long
int gcd(int a,int b)
{
return b==0?a:gcd(b,a%b);
}
const int N = 2600+10;
struct node{
int x,y,step;
};
queue<node>mmp;
int a[60][60];
int tree[N];
int lowdis[N];
int map_1[N][N];
int n;
int begin_1;
char maze[60][60];
int vis[60][60];
int dir[][4]={{-1,0},{0,-1},{0,1},{1,0}};
void prime()
{
int i,j,Min,Mindis=0,next;
memset(tree,0,sizeof(tree));
memset(lowdis,0,sizeof(lowdis));
for(i=1;i<=n;i++)
{
lowdis[i]=map_1[begin_1][i];//用lowdis[]数组记录下从起点到剩下所有点的距离
}
tree[begin_1]=1;//标记起点(即最小生成树中的点)
for(i=1;i<n;i++)
{
Min=INF;
for(j=1;j<=n;j++)
{
if(!tree[j]&&Min>lowdis[j])
{
Min=lowdis[j];//求出从当前起点到其余所有点的距离中最短的
next=j;
}
}
Mindis+=Min;//记录下整条最小树的长度
tree[next]=1;
for(j=1;j<=n;j++)
{
if(!tree[j]&&lowdis[j]>map_1[next][j])
lowdis[j]=map_1[next][j];//更新lowdis[]数组
}
}
printf("%d\n",Mindis);
}
void init(){
for(int i=1; i<=n; i++){
for(int j=1; j<=n; j++)
if(i==j) map_1[i][j]=0;
else map_1[i][j]=INF;
}
}
void init_vis(int n1,int m1)
{
for(int i=0; i<n1; i++)
{
for(int j=0; j<m1; j++)
{
if(maze[i][j] == '#')
{
vis[i][j] = 1;
}
else
{
vis[i][j] = 0;
}
}
}
}
void bfs(int x,int y)
{
int u,v;
while(!mmp.empty())
{
mmp.pop();
}
node qq;
qq.x = x;
qq.y = y;
qq.step = 0;
u = a[x][y];
vis[x][y] = 1;
mmp.push(qq);
while(!mmp.empty())
{
node mm;
int xx,yy,ss;
mm = mmp.front();
mmp.pop();
xx = mm.x;
yy = mm.y;
ss = mm.step;
if(a[xx][yy] != -1)
{
v = a[xx][yy];
map_1[u][v] = ss;
}
for(int i=0; i<4; i++)
{
if(!vis[xx+dir[i][0]][yy+dir[i][1]])
{
mm.x = xx+dir[i][0];
mm.y = yy+dir[i][1];
mm.step = ss+1;
vis[mm.x][mm.y] = 1;
mmp.push(mm);
}
}
}
}
int main()
{
int t;
scanf("%d",&t);
int n1,m1;
while(t --)
{
int cnt = 0;
memset(a,-1,sizeof(a));
scanf("%d%d",&m1,&n1);
gets(maze[0]);//就是这里,我把它换成fflush(stdin)就不行
for(int i=0; i<n1; i++)
{
gets(maze[i]);
for(int j=0; j<m1; j++)
{
if(maze[i][j] == 'A' || maze[i][j] == 'S')
{
a[i][j] = ++cnt;
}
}
}
n = cnt;
init();
for(int i=0; i<n1; i++)
{
for(int j=0; j<m1; j++)
{
if(a[i][j] != -1)
{
init_vis(n1,m1);
bfs(i,j);
}
}
}
begin_1 = 1;
prime();
}
return 0;
}
K - The Unique MST
次小生成树(模板题)
题意:判断最小生成树是否唯一
最小生成树的结果和次小生成树的结果比对就,可以判断最小生成树是否唯一
#include<stdio.h>
#include<iostream>
#include<string.h>
#define INF 0x3f3f3f3f
using namespace std;
/*
* 数组tree[]用来记录最小生成树的节点
* 数组lowdis[]记录从起点到其余所有点的距离并不断更新
* 数组map[][]记录所有数据两点之间的距离
* n是所有节点的数目,begin_1是起点
* Mindis是最小生成树的长度
主函数中输入前需要:
for(int i=1; i<=n; i++)
{
for(int j=1; j<=n; j++)
if(i==j) map_1[i][j]=0;
else map_1[i][j]=INF;
}
*/
const int N = 200+10;
int tree[N];
int lowdis[N];
int map_1[N][N];
int n;
int begin_1;
/*新开的*/
int Max[N][N]; //Max[i][j]表示在最小生成树中从i到j的路径中的最大边权
bool used[N][N];
int pre[N];
int MST,_MST;
int ans ;
int prime()
{
int i,j,Min,Mindis=0,next;
for(i=1;i<=n;i++)
{
pre[i] = 1;
lowdis[i]=map_1[begin_1][i];//用lowdis[]数组记录下从起点到剩下所有点的距离
}
tree[begin_1]=1;//标记起点(即最小生成树中的点)
pre[begin_1] = -1;
for(i=1;i<n;i++)
{
Min=INF;
int p = -1;
for(j=1;j<=n;j++)
{
if(!tree[j]&&Min>lowdis[j])
{
Min=lowdis[j];//求出从当前起点到其余所有点的距离中最短的
p = j;
}
}
Mindis+=Min;//记录下整条最小树的长度
tree[p]=1;
used[p][pre[p]] = used[pre[p]][p] = false;
for(j=1;j<=n;j++)
{
if(tree[j])
{
Max[j][p] = Max[p][j] = max(Max[pre[p]][j],lowdis[p]);
}
else
{
if(map_1[p][j]<lowdis[j])
{
lowdis[j] = map_1[p][j];
pre[j] = p;
}
}
}
}
return Mindis;
}
int second_prim()
{
int ans=INF;
for(int i=1; i<=n; i++)
for(int j=1; j<=n; j++)
if(used[i][j]) ans=min(ans,MST+map_1[i][j]-Max[i][j]);
return ans;
}
void init(){
memset(tree,0,sizeof(tree));
memset(used,false,sizeof(used));
memset(Max,-1,sizeof(Max));
for(int i=1; i<=n; i++){
for(int j=1; j<=n; j++)
if(i==j) map_1[i][j]=0;
else map_1[i][j]=INF;
}
}
int main(){
int T;
scanf("%d",&T);
while(T--)
{
int m;
scanf("%d%d",&n,&m);
init();
for(int i=0; i<m; i++)
{
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
map_1[a][b]=map_1[b][a]=c;
used[a][b]=used[b][a]=true;
}
begin_1 = 1;
MST=prime();
_MST=second_prim();
if(MST==_MST) printf("Not Unique!\n");
else printf("%d\n",MST);
}
return 0;
}
L - 还是畅通工程
模板题:
#include<stdio.h>
#include<iostream>
#include<string.h>
#define INF 0x3f3f3f3f
using namespace std;
/*
* 数组tree[]用来记录最小生成树的节点
* 数组lowdis[]记录从起点到其余所有点的距离并不断更新
* 数组map[][]记录所有数据两点之间的距离
* n是所有节点的数目,begin_1是起点
* Mindis是最小生成树的长度
主函数中输入前需要:
for(int i=1; i<=n; i++)
{
for(int j=1; j<=n; j++)
if(i==j) map_1[i][j]=0;
else map_1[i][j]=INF;
}
*/
const int N = 100+10;
int tree[N];
int lowdis[N];
int map_1[N][N];
int n;
int begin_1;
void prime()
{
int i,j,Min,Mindis=0,next;
memset(tree,0,sizeof(tree));
for(i=1;i<=n;i++)
{
lowdis[i]=map_1[begin_1][i];//用lowdis[]数组记录下从起点到剩下所有点的距离
}
tree[begin_1]=1;//标记起点(即最小生成树中的点)
for(i=1;i<n;i++)
{
next = -1;
Min=INF;
for(j=1;j<=n;j++)
{
if(!tree[j]&&Min>lowdis[j])
{
Min=lowdis[j];//求出从当前起点到其余所有点的距离中最短的
next=j;
}
}
Mindis+=Min;//记录下整条最小树的长度
tree[next]=1;
for(j=1;j<=n;j++)
{
if(!tree[j]&&lowdis[j]>map_1[next][j])
lowdis[j]=map_1[next][j];//更新lowdis[]数组
}
}
printf("%d\n",Mindis);
}
void init(){
for(int i=1; i<=n; i++){
for(int j=1; j<=n; j++)
if(i==j) map_1[i][j]=0;
else map_1[i][j]=INF;
}
}
int main(){
while(cin>>n && n)
{
init();
for(int i=1; i<=n*(n-1)/2; i++){
int a,b,c;
cin>>a>>b>>c;
map_1[a][b] = map_1[b][a] = min(map_1[a][b],c);
}
begin_1 = 1;
prime();
}
return 0;
}
M - Jungle Roads
同A题
N - 畅通工程再续
模板题
#include<stdio.h>
#include<iostream>
#include<string.h>
#include<math.h>
#define INF 1000000.0
using namespace std;
/*
* 数组tree[]用来记录最小生成树的节点
* 数组lowdis[]记录从起点到其余所有点的距离并不断更新
* 数组map[][]记录所有数据两点之间的距离
* n是所有节点的数目,begin_1是起点
* Mindis是最小生成树的长度
主函数中输入前需要:
for(int i=1; i<=n; i++)
{
for(int j=1; j<=n; j++)
if(i==j) map_1[i][j]=0;
else map_1[i][j]=INF;
}
*/
const int N = 200+10;
int tree[N];
double lowdis[N];
double map_1[N][N];
int n;
int begin_1;
double prime()
{
int i,j,next;
double Mindis=0;
memset(tree,0,sizeof(tree));
for(i=1; i<=n; i++)
{
lowdis[i]=map_1[begin_1][i];//用lowdis[]数组记录下从起点到剩下所有点的距离
}
tree[begin_1]=1;//标记起点(即最小生成树中的点)
for(i=1; i<n; i++)
{
double Min=INF;
int next = -1;
for(j=1; j<=n; j++)
{
if(!tree[j]&&Min>lowdis[j])
{
Min=lowdis[j];//求出从当前起点到其余所有点的距离中最短的
next=j;
}
}
Mindis+=Min;//记录下整条最小树的长度
tree[next]=1;
for(j=1; j<=n; j++)
{
if(!tree[j]&&lowdis[j]>map_1[next][j])
lowdis[j]=map_1[next][j];//更新lowdis[]数组
}
}
return Mindis;
}
void init()
{
for(int i=1; i<=n; i++)
{
for(int j=1; j<=n; j++)
if(i==j) map_1[i][j]=0;
else map_1[i][j]=INF;
}
}
struct point
{
double x,y;
} p[N];
double len(point a,point b)
{
double x=a.x-b.x;
double y=a.y-b.y;
return sqrt(x*x+y*y);
}
int main()
{
int t;
//freopen("N.txt","r",stdin);
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
init();
for(int i=1; i<=n; i++)
{
scanf("%lf %lf",&p[i].x,&p[i].y);
for(int j=1; j<i; j++)
{
double Len=len(p[i],p[j]);
if(Len>=10&&Len<=1000) map_1[i][j]=map_1[j][i]=Len;
}
}
begin_1 = 1;
double ans=prime();
if(ans!=INF)
{
printf("%.1f\n",ans*100);
}
else
{
printf("oh!\n");
}
}
return 0;
}