您的位置:首页 > 其它

2017暑假集训 div1 最小生成树(1)

2017-07-12 16:40 387 查看
POJ 3026

题意:一个地图上面有A或者S两种字母,其中#表示墙,空格表示可行,问最少走多少步可以使每个字母走且走一遍?

做法:首先不难想到要求一个最小生成树,那么地图的权值就是每个字母之间的最短路径,那么对每个字母跑一边BFS就可以预处理出每个字母之间的权值,最后套个最小生成树的模版,即可!

#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <string.h>
#include <queue>

using namespace std;

const int inf=0x3f3f3f3f;
int g[110][110];
char map[110][110];
int id[110][110];
int dir[][2]={ {1,0} , {-1,0}, {0,1}  ,{0,-1} };
int n,m;
int idmuch;
bool judge(int x,int y)
{
if(x<=0||y<=0||x>n||y>m) return 0;
return 1;
}
struct node
{
int x,y;
int step;
};
bool vis[110][110];
void bfs(int sx,int sy,int s)
{
memset(vis,0,sizeof(vis));
struct node u,v;
u.x=sx; u.y=sy; u.step=0;
vis[sx][sy]=1;
queue<node> que;
while(!que.empty()) que.pop();
que.push(u);
while(!que.empty())
{
u=que.front() ;que.pop();
if(id[u.x][u.y])
{
g[s][id[u.x][u.y]]=u.step;
}
for(int i=0;i<4;++i)
{
int xx=u.x+dir[i][0], yy=u.y+dir[i][1];
if(!judge(xx,yy)||vis[xx][yy]||map[xx][yy]=='#') continue;
v.x=xx;  v.y=yy; v.step=u.step+1;
vis[xx][yy]=1;  que.push(v);
}
}
}
bool used[120];
int dis[120];
void prim()
{
int sum=0;
for(int i=1;i<=idmuch;++i)
{
used[i]=0; dis[i]=g[1][i];
}
used[1]=1; dis[1]=0;
for(int i=1;i<idmuch;++i)
{
int pos=-1 ,ma=inf;
for(int j=1;j<=idmuch;++j)
{
if(!used[j]&&dis[j]<ma)
{
ma=dis[j]; pos=j;
}
}
if(pos==-1) break;
used[pos]=1; sum+=ma;
for(int j=1;j<=idmuch;++j)
{
if(!used[j]&&dis[j]>g[pos][j]) dis[j]=g[pos][j];
}
}
printf("%d\n",sum);
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
idmuch=0;
memset(id,0,sizeof(id));
scanf("%d%d",&m,&n);
gets(map[1]);
for(int i=1;i<=n;++i)
{
gets(map[i]);
for(int j=1;j<=m;++j)
{
if(map[i][j]=='A'||map[i][j]=='S')
{
id[i][j]= ++idmuch;
}
}
}
for(int i=1;i<=n;++i)
{
for(int j=1;j<=m;++j)
{
if(id[i][j]!=0)
{
bfs(i,j,id[i][j]);
}
}
}
prim();
}
return 0;
}


POJ 1679

题意:判断最小生成树是否唯一

做法:先做一次最小生成树把用过的边都存起来,枚举不用上次的边是否可以得到相同的值

#include <iostream>
#include <algorithm>
#include <stdio.h>
#include <queue>
#include <cmath>
#include <vector>
using namespace std;
const int inf=0x3f3f3f3f;
int pre[115];
int f(int x)
{
if(x!=pre[x]) pre[x]=f(pre[x]);
return pre[x];
}
void v(int x,int y)
{
int fx=f(x),fy=f(y);
pre[fy]=fx;
}
int n,m;

struct node
{
int u,v;
int w;
}l[10100];
bool cmp(const node a,const node b)
{
return a.w<b.w;
}

vector<int> ans;
bool vis[115];
int dis[115];
int k1()
{
int sum=0;
for(int i=1;i<=m;++i)
{
int a=l[i].u, b=l[i].v ,c=l[i].w;
if(f(a)==f(b)) continue;
ans.push_back(i);
v(a,b); sum+=c;
}
return sum;
}

int k2(int ford)
{
int sum=0;
int edge=0;
for(int i=1;i<=m;++i)
{
if(i==ford) continue;
int a=l[i].u, b=l[i].v ,c=l[i].w;
if(f(a)==f(b)) continue;
v(a,b); sum+=c; edge++;
}
if(edge==n-1) return sum;
return -1;
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;++i) pre[i]=i;
for(int i=1;i<=m;++i)
{
scanf("%d%d%d",&l[i].u,&l[i].v,&l[i].w);
}
sort(l,l+n,cmp);

ans.clear();
int mst=k1();

bool flag=1;
for(int i=0;i<ans.size();++i)
{
for(int j=1;j<=n;++j) pre[j]=j;
if(k2(ans[i])==mst) {flag=0; break;}
}
if(flag) printf("%d\n",mst);
else printf("Not Unique!\n");
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: