网址:https://vjudge.net/contest/66965#overview
第一题:
poj1251
裸最小生成树
#include
#include
#include
using namespace std;
const int maxn=100500;
struct node
{
int x;
int y;
int w;
}a[maxn];
int n,k;
char s,v;
int cnt;
int w;
int f[30];
int findf(int x)
{
if(f[x]==x)
return x;
else
{
//f[x]=findf(f[x]);
return findf(f[x]);
}
}
int join(int x,int y)
{
int t1=findf(x);
int t2=findf(y);
if(t1==t2)
return 1;
else
{
f[t2]=t1;
return 0;
}
}
int cmp(node x,node y)
{
return x.w>n)
{
if(n==0)
break;
for(int i=1;i<=30;i++)
f[i]=i;
cnt=0;
for(int i=1;i>s>>k;
for(int i=1;i<=k;i++)
{
cin>>v>>w;
a[++cnt].x=s-'A'+1;
a[cnt].y=v-'A'+1;
a[cnt].w=w;
}
}
sort(a+1,a+1+cnt,cmp);
int cot=0;
int cost=0;
for(int i=1;i<=cnt;i++)
{
if(join(a[i].x,a[i].y)==0)
{
cot++;cost+=a[i].w;
}
if(cot==n-1)
break;
}
cout<
第二题
poj1287
裸最小生成树
#include
#include
#include
using namespace std;
const int maxn=100500;
struct node
{
int x,y,w;
}a[maxn];
int f[100];
int cnt,cot;
int n,m;
int x,y,w;
bool cmp(node xx,node yy)
{
return xx.w>n>>m)
{
if(n==0)
break;
for(int i=1;i<=m;i++)
{
cin>>x>>y>>w;
a[i].x=x;
a[i].y=y;
a[i].w=w;
}
sort(a+1,a+1+m,cmp);
for(int i=1;i<=n;i++)
f[i]=i;
cnt=0;
int cost=0;
for(int i=1;i<=m;i++)
{
if(join(a[i].x,a[i].y))
{
cnt++;
cost+=a[i].w;
if(cnt==n-1)
break;
}
}
cout<
第三题
poj2031
最小生成树+圆的距离
#include
#include
#include
#include
#include
using namespace std;
const int maxn=20050;
struct node
{
int x,y;
double w;
}a[maxn];
struct circle
{
double x,y,z,r;
}c[205];
int f[205];
int n;
int cnt;
int findf(int u)
{
if(f[u]==u)
return u;
else
{
f[u]=findf(f[u]);
return f[u];
}
}
bool join(int u,int v)
{
int t1=findf(u);
int t2=findf(v);
if(t1==t2)
{
return false;
}
else
{
f[t2]=t1;
return true;
}
}
bool cmp(node u,node v)
{
return u.w>n)
{
int cot=0;
if(n==0)
break;
for(int i=1;i<=n;i++)
{
cin>>c[i].x>>c[i].y>>c[i].z>>c[i].r;
}
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
{
if(i==j)
continue;
else
{
a[++cot].x=i;a[cot].y=j;a[cot].w=juage(i,j);
}
}
for(int i=1;i<=n;i++)
sort(a+1,a+1+cot,cmp);
for(int i=1;i<=n;i++)
f[i]=i;
cnt=0;
double cost=0;
for(int i=1;i<=cot;i++)
{
if(join(a[i].x,a[i].y))
{
cost+=a[i].w;
cnt++;
}
if(cnt==n-1)
break;
}
printf("%.3f\n",cost);
}
}
第四题:
poj2421
部分边+最小生成树,先把给出的边扔进并查集里
#include
#include
#include
#include
using namespace std;
const int maxn=100500;
struct node
{
int x,y,w;
}a[maxn];
int g[105][105];
int n,cnt;
int f[105];
int cmp(node x,node y)
{
return x.w>n;
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
cin>>g[i][j];
int cost=0;
int cot=0;
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
{
if(i==j)
continue;
a[++cot].x=i;a[cot].y=j;a[cot].w=g[i][j];
}
sort(a+1,a+1+cot,cmp);
for(int i=1;i<=n;i++)
f[i]=i;
int q;
cin>>q;
while(q--)
{
cin>>x>>y;
if(join(x,y))
{
cnt++;
}
join(x,y);
}
for(int i=1;i<=cot;i++)
{
if(cnt==n-1)
break;
else
{
if(join(a[i].x,a[i].y))
{
cnt++;
cost+=a[i].w;
}
}
}
cout<
第五题:
zoj1586
用prime写的,把边权改成正常边权+点权
#include
#include
#include
#include
#include
using namespace std;
const int maxn=1005;
const int inf=0x3f3f3f3f;
struct node
{
int num;
int dist;
node(int _num=0,int _dist=0):num(_num),dist(_dist){}
friend bool operator<(node a,node b)
{
return a.dist>b.dist;
}
};
struct Edge
{
int next;
int to;
int w;
}edge[maxn*maxn];
int g[maxn][maxn];
int c[maxn];
int n;
int visit[maxn];
int dist[maxn];
int head[maxn];
int cnt;
void add(int u,int v,int w)
{
edge[cnt].next=head[u];
edge[cnt].to=v;
edge[cnt].w=w;
head[u]=cnt++;
}
int prime(int u)
{
int cost=0;
fill(dist+1,dist+1+n,inf);
fill(visit+1,visit+1+n,0);
dist[u]=0;
priority_queueq;
q.push(node(u,dist[u]));
while(!q.empty())
{
node x=q.top();q.pop();
int now=x.num;
if(visit[now])
continue;
visit[now]=1;
cost+=dist[now];
for(int i=head[now];i!=-1;i=edge[i].next)
{
int v=edge[i].to;
if(visit[v])
continue;
if(dist[v]>edge[i].w)
{
dist[v]=edge[i].w;
q.push(node(v,dist[v]));
}
}
}
return cost;
}
void init()
{
memset(head,-1,sizeof(head));
cnt=0;
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
int start=inf;
int pos=1;
init();
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d",&c[i]);
if(start
第六题
poj1789
裸最小生成树
#include
#include
#include
#include
#include
using namespace std;
const int maxn=2050;
const int inf=0x3f3f3f3f;
struct node
{
int num;
int dist;
node(int _num=0,int _dist=0):num(_num),dist(_dist){}
friend bool operator<(node a,node b)
{
return a.dist>b.dist;
}
};
struct Edge
{
int next,to,w;
}edge[maxn*maxn];
int head[maxn];
int cnt;
int dist[maxn];
int visit[maxn];
int n;
char s[maxn][10];
void add(int u,int v,int w)
{
edge[cnt].next=head[u];
edge[cnt].to=v;
edge[cnt].w=w;
head[u]=cnt++;
}
int prime(int u)
{
int cost=0;
fill(dist+1,dist+1+n,inf);
fill(visit+1,visit+1+n,0);
dist[u]=0;
priority_queueq;
q.push(node(u,dist[u]));
while(!q.empty())
{
node x=q.top();q.pop();
int now=x.num;
if(visit[now])
continue;
visit[now]=1;
cost+=dist[now];
for(int i=head[now];i!=-1;i=edge[i].next)
{
int v=edge[i].to;
if(visit[v])
continue;
if(dist[v]>edge[i].w)
{
dist[v]=edge[i].w;
q.push(node(v,dist[v]));
}
}
}
return cost;
}
int main()
{
while(scanf("%d",&n)!=EOF)
{
if(n==0)
break;
memset(head,-1,sizeof(head));
cnt=0;
int tmp;
for(int i=1;i<=n;i++)
scanf("%s",s[i]);
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
tmp=0;
if(i==j)
continue;
for(int k=0;k<7;k++)
{
if(s[i][k]!=s[j][k])
tmp++;
}
add(i,j,tmp);
}
}
int ans=prime(1);
printf("The highest possible quality is 1/%d.\n",ans);
}
}
第七题
poj2349
反着来,每一个s可以减少s-1条边,先处理s,然后就行了
#include
#include
#include
#include
#include
using namespace std;
const int maxn=505;
struct node
{
int x,y;
double w;
}a[maxn*maxn];
int cot,cnt;
double ans;
int s,p;
double x[maxn],y[maxn];
int f[maxn];
int findf(int u)
{
if(f[u]==u)
return u;
else
{
f[u]=findf(f[u]);
return f[u];
}
}
bool join(int u,int v)
{
int t1=findf(u);
int t2=findf(v);
if(t1==t2)
{
return false;
}
else
{
f[t2]=t1;
return true;
}
}
bool cmp(node u,node v)
{
return u.w>tt;
while(tt--)
{
ans=cot=cnt=0;
cin>>s>>p;
for(int i=1;i<=p;i++)
cin>>x[i]>>y[i];
for(int i=1;i<=p;i++)
{
for(int j=1;j<=p;j++)
{
if(i==j)
continue;
else
{
a[++cot].x=i;a[cot].y=j;a[cot].w=sqrt((x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j]));
}
}
}
sort(a+1,a+1+cot,cmp);
for(int i=1;i<=p;i++)
f[i]=i;
if(s>0)
s--;
for(int i=1;i<=cot;i++)
{
if(cnt+s>=p-1)
break;
if(join(a[i].x,a[i].y))
{
cnt++;
ans=a[i].w;
}
}
printf("%.2f\n",ans);
}
}
第八题
poj1751
这道题容易超时,尽量别用浮点数,两个之间的距离可以直接用整数
#include
#include
#include
#include
#include
using namespace std;
const int maxn=800;
struct node
{
int x,y;
double w;
}a[maxn*maxn];
int cot,cnt;
int n,k;
int x[maxn],y[maxn];
int f[maxn];
int findf(int u)
{
if(f[u]==u)
return u;
else
{
f[u]=findf(f[u]);
return f[u];
}
}
bool join(int u,int v)
{
int t1=findf(u);
int t2=findf(v);
if(t1==t2)
{
return false;
}
else
{
f[t2]=t1;
return true;
}
}
bool cmp(node u,node v)
{
return u.w=(n-1))
break;
if(join(a[i].x,a[i].y))
{
cnt++;
printf("%d %d\n",a[i].x,a[i].y);
}
}
}
第九题:
裸最小生成树
#include
#include
#include
#include
#include
using namespace std;
const int maxn=110;
struct node
{
int x,y,w;
}a[maxn*maxn];
int cot,cnt,ans;
int n,k;
int x[maxn][maxn];
int f[maxn];
int findf(int u)
{
if(f[u]==u)
return u;
else
{
f[u]=findf(f[u]);
return f[u];
}
}
bool join(int u,int v)
{
int t1=findf(u);
int t2=findf(v);
if(t1==t2)
{
return false;
}
else
{
f[t2]=t1;
return true;
}
}
bool cmp(node u,node v)
{
return u.w
第十题
最小生成树+BFS预处理
题意:就是每次到A,S就可以分其他路径
注意这题有个傻逼地方,m,n输完后,n后面跟着一串空格。。这个要自己注意,我是拿gets直接输掉了
#include
#include
#include
#include
#include
using namespace std;
const int inf=0x3f3f3f3f;
const int maxn=100500;
struct node
{
int num;
int dist;
node(int _num,int _dist):num(_num),dist(_dist){}
friend bool operator<(node a,node b)
{
return a.dist>b.dist;
}
};
struct Edge
{
int next,to,w;
}edge[maxn];
struct Node
{
int x,y,s;
}que[2505];
char s[550][550];
int dist[2505];
bool visit[2505];
bool vis[550][550];
int next[4][2]={{1,0},{0,1},{-1,0},{0,-1}};
int n,m,cnt,Start,End;
int head[maxn];
void add(int u,int v,int w)
{
edge[cnt].next=head[u];edge[cnt].to=v;edge[cnt].w=w;head[u]=cnt++;
edge[cnt].next=head[v];edge[cnt].to=u;edge[cnt].w=w;head[v]=cnt++;
}
void bfs(int st,int en)
{
memset(vis,0,sizeof(vis));
int tail,head;
int tx,ty;
tail=head=1;
vis[st][en]=1;
que[tail].x=st;que[tail].y=en;que[tail].s=0;
tail++;
while(headn||ty<1||ty>m)
continue;
if(s[tx][ty]!='#'&&vis[tx][ty]==0)
{
que[tail].x=tx;
que[tail].y=ty;
que[tail].s=que[head].s+1;
vis[tx][ty]=1;
if(s[tx][ty]=='A'||s[tx][ty]=='S')
add((st-1)*m+en,(tx-1)*m+ty,que[tail].s);
tail++;
}
}
head++;
}
}
int prime(int u)
{
memset(dist,inf,sizeof(dist));
memset(visit,0,sizeof(visit));
int sum=0;
int lowcast=0;
priority_queue q;
dist[u]=0;
q.push(node(u,dist[u]));
while(!q.empty())
{
node x=q.top();q.pop();
int now=x.num;
if(visit[now]==1)
continue;
visit[now]=1;
sum=sum+dist[now];
for(int i=head[now];i!=-1;i=edge[i].next)
{
int v=edge[i].to;
if(visit[v]==1)
continue;
if(dist[v]>edge[i].w)
{
dist[v]=edge[i].w;
q.push(node(v,dist[v]));
}
}
}
return sum;
}
int main()
{
char ss[100];
int T;
cin>>T;
while(T--)
{
memset(head,-1,sizeof(head));cnt=0;
cin>>m>>n;
gets(ss);
for(int i=1;i<=n;i++)
gets(s[i]+1);
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
{
if(s[i][j]=='S'||s[i][j]=='A')
bfs(i,j);
if(s[i][j]=='S')
Start=i,End=j;
}
int ans=prime((Start-1)*n+End);
printf("%d\n",ans);
}
}
第十一题
poj1679
裸次小生成树
#include
#include
#include
#include
const int inf=0x3f3f3f3f;
const int maxn=1005;
using namespace std;
bool visit[maxn];
int Map[maxn][maxn];
bool used[maxn][maxn];//两个点的那条边是否被使用过;
int Max[maxn][maxn];//记录MST中两个点的最大距离;
int dist[maxn];
int pre[maxn];//保存父节点;
int n,m;
int prime()
{
int ans=0;
memset(visit,false,sizeof(visit));
memset(Max,0,sizeof(Max));
memset(used,0,sizeof(used));
visit[1]=1;pre[1]=-1;
for(int i=2;i<=n;i++)
{
dist[i]=Map[1][i];
pre[i]=1;
}
dist[1]=0;
for(int i=1;i<=n-1;i++)
{
int lowcast=inf;
int temp=-1;
for(int j=1;j<=n;j++)
{
if(!visit[j]&&lowcast>dist[j])
{
lowcast=dist[j];
temp=j;
}
}
if(lowcast==inf)//这说明有点不连通;
return -1;
ans+=lowcast;//最小生成树的值;
visit[temp]=1;
used[temp][pre[temp]]=used[pre[temp]][temp]=1;
for(int j=1;j<=n;j++)
{
if(visit[j])
Max[j][temp]=Max[temp][j]=max(Max[j][pre[temp]],dist[temp]);//数组的作用是记录MST里面两个点的最大距离;
if(!visit[j]&&dist[j]>Map[temp][j])
{
dist[j]=Map[temp][j];
pre[j]=temp;
}
}
}
return ans;
}
int ans;
int SMST()
{
int minn=inf;
for(int i=1;i<=n;i++)
{
for(int j=i+1;j<=n;j++)
{
if(Map[i][j]!=inf&&(!used[i][j]))
{
minn=min(minn,ans+Map[i][j]-Max[i][j]);
}
}
}
if(minn==inf)
return -1;//没有最小生成树;
return minn;
}
int main()
{
int t;
int x,y,w;
cin>>t;
while(t--)
{
cin>>n>>m;
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
{
if(i==j)
Map[i][j]=0;
else
Map[i][j]=inf;
}
for(int i=1;i<=m;i++)
{
cin>>x>>y>>w;
Map[x][y]=w;Map[y][x]=w;
}
ans=prime();
if(ans==-1)
{
printf("Not Unique!\n");
continue;
}
if(ans==SMST())printf("Not Unique!\n");
else printf("%d\n",ans);
}
return 0;
}
第十二题
hdu1233
裸最小生成树
#include
#include
#include
#include
#include
#define inf 0x3f3f3f3f
#define maxn 1005000
using namespace std;
struct node
{
int num;
int dist;
node(int _num=0,int _dist=0):num(_num),dist(_dist){}
friend bool operator<(node a,node b)
{
if(a.dist==b.dist)
return a.num>b.num;
return a.dist>b.dist;
}
};
struct Edge
{
int next;
int to;
int w;
}edge[maxn];
int dist[100500];
int cnt;
int head[maxn];
int visit[100500];
void add(int u,int v,int w)
{
edge[cnt].next=head[u];edge[cnt].w=w;
edge[cnt].to=v;head[u]=cnt++;
}
int prime(int u)
{
memset(dist,inf,sizeof(dist));
memset(visit,0,sizeof(visit));
int sum=0;
int lowcast=0;
priority_queue q;
dist[u]=0;
q.push(node(u,dist[u]));
while(!q.empty())
{
node x=q.top();q.pop();
int now=x.num;
if(visit[now]==1)
continue;
visit[now]=1;
sum=sum+dist[now];
for(int i=head[now];i!=-1;i=edge[i].next)
{
int v=edge[i].to;
if(visit[v]==1)
continue;
if(dist[v]>edge[i].w)
{
dist[v]=edge[i].w;
q.push(node(v,dist[v]));
}
}
}
return sum;
}
int main()
{
int n,m;
int x,y,w;
while(scanf("%d",&n)&&n)
{
m=n*(n-1)/2;
memset(head,-1,sizeof(head));cnt=0;
for(int i=1;i<=m;i++)
{
scanf("%d%d%d",&x,&y,&w);
add(x,y,w);add(y,x,w);
}
int ans=prime(1);
printf("%d\n",ans);
}
}
第十三题
好像和前面一样的,所以没写
第十四题
#include
#include
#include
#include
#include
const int inf=0x7fffffff;
using namespace std;
struct node
{
double x;
double y;
}a[105];
int n;
double Map[105][105];
double dist[105];
bool visit[105];
int flag;
double prime(int x)
{
memset(visit,0,sizeof(visit));
flag=0;
int temp=inf;
double lowcast;
double sum=0;
for(int i=1;i<=n;i++)
dist[i]=Map[x][i];
visit[x]=1;
for(int i=1;i<=n-1;i++)
{
lowcast=inf;
for(int j=1;j<=n;j++)
{
if(visit[j]==0&&dist[j]1000)
flag=1;
for(int k=1;k<=n;k++)
{
if(visit[k]==0&&dist[k]>Map[temp][k])
dist[k]=Map[temp][k];
}
}
return sum;
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%lf%lf",&a[i].x,&a[i].y);
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
if(i==j)
Map[i][j]=0;
else
Map[i][j]=inf;
}
}
for(int i=1;i<=n;i++)
{
for(int j=i+1;j<=n;j++)
{
Map[i][j]=sqrt((a[i].x-a[j].x)*(a[i].x-a[j].x)+(a[i].y-a[j].y)*(a[i].y-a[j].y));
Map[j][i]=sqrt((a[i].x-a[j].x)*(a[i].x-a[j].x)+(a[i].y-a[j].y)*(a[i].y-a[j].y));
if(Map[i][j]>1000||Map[i][j]<10)
{
Map[i][j]=inf;
Map[j][i]=inf;
}
}
}
double x=prime(1);
if(flag==1||x>=inf)
printf("oh!\n");
else
{
x=x*100;
printf("%.1lf\n",x);
}
}
return 0;
}