A - Jungle Roads
Prim算法:
#include<string>
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
const int INF = 0x3f3f3f3f;
int a[550][550], d[550], v[550],k;
int n,m,ans;
void prim(){
memset(v,0,sizeof(v));
for(int i = 1; i <= n; i++)
d[i] = a[1][i];
v[1]=1;
ans=0;
for(int i=1;i<n;i++){
int x=0,minnum=INF;
for(int j=1;j<=n;j++){
if(!v[j]&&(x==0||d[j]<minnum))x=j,minnum=d[j];
}
v[x]=1;
if(minnum!=INF)
ans+=minnum;
for(int y=1;y<=n;y++){
if(!v[y])d[y]=min(d[y],a[x][y]);
}
}
printf("%d\n",ans);
}
int main(){
while(scanf("%d", &n)&&n)
{
memset(a,INF,sizeof(a));
for(int i=1;i<=n;i++)a[i][i]=0;
for(int i=1;i<=n-1;i++){
int k1;
string c1;
cin>>c1>>k1;
for(int j=1;j<=k1;j++){
int k2;
string c2;
cin>>c2>>k2;
int tmp1=c1[0]-'A'+1;
int tmp2=c2[0]-'A'+1;
a[tmp1][tmp2]=a[tmp2][tmp1]=min(a[tmp1][tmp2],k2);
}
}
prim();
}
return 0;
}
B:Networking
Kruskal算法
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
struct rec{int x,y,z; }edge[500010];
int fa[100010],n,m,ans;
bool operator<(rec a,rec b){
return a.z<b.z;
}
int get(int x){
if(x==fa[x])return x;
return fa[x]=get(fa[x]);
}
int main(){
while(scanf("%d",&n)&&n){
ans=0;
memset(fa,0,sizeof(fa));
scanf("%d",&m);
for(int i=1;i<=m;i++)
cin>>edge[i].x>>edge[i].y>>edge[i].z;
sort(edge+1,edge+1+m);
for(int i = 1;i<=n;i++)fa[i]=i;
for(int i = 1;i<=m;i++){
int x=get(edge[i].x);
int y=get(edge[i].y);
if(x==y)continue;
fa[x]=y;
ans+=edge[i].z;
}
cout<<ans<<endl;
}
return 0;
}
C - Building a Space Station
#include<string>
#include <cstdio>
#include<cmath>
#include <cstring>
#include <iostream>
using namespace std;
const int INF = 0x3f3f3f3f;
double a[550][550],d[550], v[550],k;
int n;
double ans;
double x[550],y[550],z[550],r[550];
void prim(){
memset(v,0,sizeof(v));
for(int i = 1; i <= n; i++)
d[i] = a[1][i];
v[1]=1;
ans=0;
for(int i=1;i<n;i++){
int x=0;
double minnum=INF;
for(int j=1;j<=n;j++){
if(!v[j]&&(x==0||d[j]<minnum))x=j,minnum=d[j];
}
v[x]=1;
if(minnum!=INF)
ans+=minnum;
for(int y=1;y<=n;y++){
if(!v[y])d[y]=min(d[y],a[x][y]);
}
}
printf("%.3lf\n",ans);
}
double dis(double a,double b,double c,double d,double e,double f,double g,double h){
return sqrt( (a-b)*(a-b) + (c-d)*(c-d) + (e-f)*(e-f) )-g-h;
}
int main(){
while(scanf("%d", &n)&&n)
{
memset(a,INF,sizeof(a));
for(int i=1;i<=n;i++)a[i][i]=0;
for(int i=1;i<=n;i++){
scanf("%lf%lf%lf%lf",&x[i],&y[i],&z[i],&r[i]);
}
for(int i=1;i<n;i++){
for(int j=i+1;j<=n;j++){
double zz=dis(x[i],x[j],y[i],y[j],z[i],z[j],r[i],r[j]);
if(zz>0)a[i][j]=a[j][i]=zz;
else a[i][j]=a[j][i]=0;
}
}
prim();
}
return 0;
}
D - Constructing Roads
#include<string>
#include <cstdio>
#include<cmath>
#include <cstring>
#include <iostream>
#define ll long long
using namespace std;
const int INF = 0x3f3f3f3f;
ll a[550][550],d[550], v[550];
int n;
ll ans;
double x[550],y[550],z[550],r[550];
void prim(){
memset(v,0,sizeof(v));
for(int i = 1; i <= n; i++)
d[i] = a[1][i];
v[1]=1;
ans=0;
for(int i=1;i<n;i++){
int x=0;
ll minnum=INF;
for(int j=1;j<=n;j++){
if(!v[j]&&(x==0||d[j]<minnum))x=j,minnum=d[j];
}
v[x]=1;
if(minnum!=INF)
ans+=minnum;
for(int y=1;y<=n;y++){
if(!v[y])d[y]=min(d[y],a[x][y]);
}
}
printf("%lld\n",ans);
}
int main(){
scanf("%d", &n);
memset(a,INF,sizeof(a));
for(int i=1;i<=n;i++)a[i][i]=0;
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
scanf("%lld",&a[i][j]);
}
}
int k;
scanf("%d",&k);
for(int i=0;i<k;i++){
int x,y;
scanf("%d%d",&x,&y);
a[x][y]=a[y][x]=0;
}
prim();
return 0;
}
E - Truck History
题意:俩个不同字符串间的相同位置的不同字符个数就是俩个字符串的距离然后用最小生成树找出答案
#include<string>
#include <cstdio>
#include<cmath>
#include <cstring>
#include <iostream>
#define ll long long
using namespace std;
const int INF = 0x3f3f3f3f;
const int N = 2500;
ll a[N][N],d[N], v[N];
char str[N][10];
int n;
ll ans;
void prim(){
memset(v,0,sizeof(v));
for(int i = 1; i <= n; i++)
d[i] = a[1][i];
v[1]=1;
ans=0;
for(int i=1;i<n;i++){
int x=0;
ll minnum=INF;
for(int j=1;j<=n;j++){
if(!v[j]&&(x==0||d[j]<minnum))x=j,minnum=d[j];
}
v[x]=1;
if(minnum==INF)break;
ans+=minnum;
for(int y=1;y<=n;y++){
if(!v[y])d[y]=min(d[y],a[x][y]);
}
}
printf("The highest possible quality is 1/%d.\n",ans);
}
int main(){
while(scanf("%d", &n)!=EOF&&n){
memset(a,INF,sizeof(a));
for(int i=1;i<=n;i++){
scanf("%s",str[i]);
}
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
int tmp=0;
for(int k=0;k<7;k++){
if(str[i][k]!=str[j][k])tmp++;
}
a[i][j]=a[j][i]=tmp;
}
}
prim();
}
return 0;
}
F - Arctic Network
#include<string>
#include <cstdio>
#include<cmath>
#include <cstring>
#include<algorithm>
#include <iostream>
#define ll long long
using namespace std;
const int INF = 0x3f3f3f3f;
const int N = 2500;
double a[N][N],d[N];
bool v[N];
double dis[N];
double x[N],y[N];
int n,k;
double prim(){
double ans = 0;
memset(v,0,sizeof(v));
for(int i = 1; i <= n; i++)
d[i] = a[1][i];
v[1]=1;
ans=0;
for(int i=1;i<n;i++){
int x=0;
double minnum=INF;
for(int j=1;j<=n;j++){
if(!v[j]&&(x==0||d[j]<minnum))x=j,minnum=d[j];
}
v[x]=true;
//if(minnum==INF)break;
ans+=minnum;
dis[k++]=minnum;
//cout<<dis[k-1]<<" ";
for(int y=1;y<=n;y++){
if(!v[y])d[y]=min(d[y],a[x][y]);
}
}
return ans;
}
double dd(double x1,double x2,double y1,double y2){
return sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
}
int main(){
int T,m;
scanf("%d",&T);
while(T--){
scanf("%d%d", &m,&n);
k=0;
memset(dis,0,sizeof(dis));
memset(a,INF,sizeof(a));
for(int i=1;i<=n;i++){
scanf("%lf%lf",&x[i],&y[i]);
}
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]=a[j][i]=dd(x[i],x[j],y[i],y[j]);
}
}
prim();
sort(dis,dis+k);
//cout<<"k="<<k<<endl;
printf("%.2lf\n",dis[k-m]);
}
return 0;
}
G - Highways
#include<string>
#include <cstdio>
#include<cmath>
#include <cstring>
#include<algorithm>
#include <iostream>
#define ll long long
using namespace std;
const int INF = 0x3f3f3f3f;
const int N = 1050;
double a[N][N],d[N];
bool v[N];
int dis[N];
double x[N],y[N];
int n,k;
void prim(){
memset(v,0,sizeof(v));
for(int i = 1; i <= n; i++)
d[i] = a[1][i] , dis[i] = 1;
v[1]=1;
for(int i=1;i<n;i++){
int x=0;
double minnum=INF;
for(int j=1;j<=n;j++){
if(!v[j]&&(x==0||d[j]<minnum))x=j,minnum=d[j];
}
v[x]=true;
if(a[dis[x]][x]!=0)printf("%d %d\n",dis[x],x);
d[x]=0;
for(int y=1;y<=n;y++){
if(!v[y]&&d[y]>d[x]+a[x][y]){
d[y]=d[x]+a[x][y];
dis[y]=x;
}
}
}
return;
}
double dd(double x1,double x2,double y1,double y2){
return sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
}
int main(){
scanf("%d",&n);
memset(a,INF,sizeof(a));
for(int i=1;i<=n;i++){
scanf("%lf%lf",&x[i],&y[i]);
}
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]=a[j][i]=dd(x[i],x[j],y[i],y[j]);
}
}
int q;
scanf("%d",&q);
while(q--){
int xx,yy;
scanf("%d%d",&xx,&yy);
a[xx][yy]=a[yy][xx]=0;
}
prim();
return 0;
}
H - Agri-Net
#include<string>
#include <cstdio>
#include<cmath>
#include <cstring>
#include<algorithm>
#include <iostream>
#define ll long long
using namespace std;
const int INF = 0x3f3f3f3f;
const int N = 200;
ll a[N][N],d[N];
bool v[N];
ll dis[N];
int n;
ll prim(){
ll ans=0;
memset(v,0,sizeof(v));
for(int i = 1; i <= n; i++)
d[i] = a[1][i];
v[1]=1;
for(int i=1;i<n;i++){
int x = 0;
ll minnum = INF;
for(int j=1;j<=n;j++){
if(!v[j]&&(x==0||d[j]<minnum))x=j,minnum=d[j];
}
v[x]=true;
d[x]=0;
ans += minnum;
for(int y=1;y<=n;y++){
if(!v[y]&&d[y]>d[x]+a[x][y]){
d[y]=d[x]+a[x][y];
}
}
}
return ans;
}
int main(){
while(scanf("%d",&n)!=EOF){
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
scanf("%lld",&a[i][j]);
}
}
printf("%lld\n",prim());
}
return 0;
}
I - Borg Maze
题解:BFS+MST,非常好玩的一个题,先把图中每个A和S当成点然后用BFS找出每个点之间的距离,再用MST找出答案
#include<string>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<queue>
#define ll long long
using namespace std;
const int INF = 0x3f3f3f3f;
const int N = 300;
const int MAXN = 3000;
int a[MAXN][MAXN],d[MAXN];
int dx[]={-1,1,0,0};
int dy[]={0,0,-1,1};
int mp[N][N];
char str[N][N];
bool v[MAXN],vis[N][N];
int n,m;
struct p{
int x,y,z;
};
int prim(int n){
ll ans=0;
memset(v,0,sizeof(v));
for(int i = 0; i < n; i++)
d[i] = a[0][i];
d[0]=0;
v[0]=1;
for(int i=1;i<n;i++){
int x = 0;
int minnum = INF;
for(int j=0;j<n;j++){
if(!v[j]&&(x==0||d[j]<minnum))x=j,minnum=d[j];
}
v[x]=true;
d[x]=0;
ans += minnum;
for(int y=1;y<=n;y++){
if(!v[y]&&d[y]>d[x]+a[x][y]){
d[y]=d[x]+a[x][y];
}
}
}
return ans;
}
void bfs(int i,int j){
int x=i,y=j;
memset(vis,0,sizeof(vis));
queue<p>q;
vis[i][j] = true;
a[mp[i][j]][mp[i][j]]=0;
p tmp2;
tmp2.x=i,tmp2.y=j,tmp2.z=0;
q.push(tmp2);
while(!q.empty()){
p tmp1=q.front();
q.pop();
for(int i=0;i<4;i++){
int tx=tmp1.x+dx[i];
int ty=tmp1.y+dy[i];
if(tx<n&&tx>=0&&ty<m&&ty>=0&&str[tx][ty]!='#'&&!vis[tx][ty]){
if(mp[tx][ty]!=-1)
a[mp[x][y]][mp[tx][ty]]=tmp1.z+1;
p tmp3;
tmp3.x=tx,tmp3.y=ty,tmp3.z=tmp1.z+1;
q.push(tmp3);
vis[tx][ty]=true;
}
}
}
}
int main(){
int T;
scanf("%d",&T);
char s[30];
while(T--){
scanf("%d%d ",&m,&n);
for(int i = 0;i < n;i++)
{
gets(str[i]);
}
int pos=0;
memset(mp,-1,sizeof(mp));
for(int i=0;i<n;i++){
for(int j=0;j<m;j++){
if(str[i][j]=='A'||str[i][j]=='S'){
mp[i][j]=pos++;
}
}
}
for(int i=0;i<n;i++){
for(int j=0;j<m;j++){
if(mp[i][j]!=-1){
bfs(i,j);
}
}
}
int ans = prim(pos);
printf("%d\n",ans);
}
return 0;
}
J - The Unique MST
找出是否有重复的路
#include<string>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<queue>
#define ll long long
using namespace std;
const int INF = 0x3f3f3f3f;
const int N = 200;
const int MAXN = 3005;
int a[N][N],d[MAXN];
bool v[MAXN];
int n,m,k,ans,f,flag;
int prim(int n){
memset(v,0,sizeof(v));
for(int i = 1; i <= n; i++)
d[i] = a[1][i];
v[1]=true;
ans=flag=0;
for(int i=1;i<n;i++){
int x = 0;
int minnum = INF;
for(int j=1;j<=n;j++){
if(!v[j]&&(x==0||d[j]<minnum))x=j,minnum=d[j];
}
f = 0;
for(int j=1;j<=n;j++){
if(v[j]&&a[j][x]==minnum)f++;
}
if(f>1){
flag=1;
return 0;
}
v[x]=true;
ans+=minnum;
for(int y=1;y<=n;y++){
if(!v[y]&&d[y]>a[x][y]){
d[y]=a[x][y];
}
}
}
return ans;
}
int main(){
int T;
scanf("%d",&T);
while(T--){
scanf("%d%d ",&n,&m);
memset(a,INF,sizeof(a));
for(int i=1;i<=n;i++)a[i][i]=0;
for(int i=1;i<=m;i++){
int a1,a2,a3;
scanf("%d%d%d",&a1,&a2,&a3);
a[a1][a2]=a[a2][a1]=min(a[a2][a1],a3);
}
int sum = prim(n);
if(flag)printf("Not Unique!\n");
else printf("%d\n",sum);
}
return 0;
}
K - 还是畅通工程
#include<iostream>
using namespace std;
#include<map>
#include<algorithm>
#include<string>
#include<cstring>
#define ll long long
int fa[101000],n,m,ans;
struct rec{
int x,y,z;
bool operator <(const rec b)const {
return z<b.z;
}
}edge[501000];
int get(int key){
if(fa[key]==key)return key;
return fa[key]=get(fa[key]);
}
int main(){
while(scanf("%d",&n)!=EOF&&n){
m=n*(n-1)/2;
ans=0;
for(int i=1;i<=n;i++)fa[i]=i;
for(int i=1;i<=m;i++){
int x,y;
scanf("%d%d%d",&edge[i].x,&edge[i].y,&edge[i].z);
}
sort(edge+1,edge+1+m);
for(int i=1;i<=m;i++){
int tx=get(edge[i].x);
int ty=get(edge[i].y);
if(tx==ty)continue;
fa[tx]=ty;
ans+=edge[i].z;
}
int f=0;
for(int i=1;i<=n;i++){
if(fa[i]==i){
f++;
}
}
if(f!=1)printf("?\n");
else printf("%d\n",ans);
}
return 0;
}
L与A重了
M - 畅通工程再续
#include<iostream>
using namespace std;
#include<map>
#include<algorithm>
#include<string>
#include<cstring>
#define ll long long
int fa[101000],n,m;
double ans;
struct P{
int x,y;
}p[501000];
struct rec{
int x,y;
double z;
bool operator <(const rec b)const {
return z<b.z;
}
}edge[501000];
int get(int key){
if(fa[key]==key)return key;
return fa[key]=get(fa[key]);
}
double d(int x1,int x2,int y1,int y2){
return sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
}
int main(){
int T;
while(scanf("%d",&T)!=EOF){
while(T--){
scanf("%d",&n);
ans=0;
for(int i=1;i<=n;i++)fa[i]=i;
for(int i=1;i<=n;i++){
scanf("%d%d",&p[i].x,&p[i].y);
}
int pos=1;
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
if(i!=j){
double z = d(p[i].x,p[j].x,p[i].y,p[j].y);
if(z<10||z>1000)continue;
edge[pos].x=i;
edge[pos].y=j;
edge[pos].z=z;
//printf("%d -> %d -> z = %lf\n",i,j,edge[pos].z);
pos++;
}
}
}
//cout<<"pos = "<<pos<<endl;
//pos/=2;
//cout<<"pos = "<<pos<<endl;
sort(edge+1,edge+1+pos);
for(int i=1;i<=pos;i++){
int tx=get(edge[i].x);
int ty=get(edge[i].y);
if(tx==ty)continue;
fa[tx]=ty;
ans+=edge[i].z;
}
int f=0;
for(int i=1;i<=n;i++){
if(fa[i]==i){
f++;
}
}
if(f!=1)printf("oh!\n");
else printf("%.1lf\n",ans*100);
}
}
return 0;
}