2017暑假集训 div1 最小生成树(1)
2017-07-12 16:40
387 查看
POJ 3026
题意:一个地图上面有A或者S两种字母,其中#表示墙,空格表示可行,问最少走多少步可以使每个字母走且走一遍?
做法:首先不难想到要求一个最小生成树,那么地图的权值就是每个字母之间的最短路径,那么对每个字母跑一边BFS就可以预处理出每个字母之间的权值,最后套个最小生成树的模版,即可!
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;
}
题意:一个地图上面有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;
}
相关文章推荐
- 2017暑假集训 div1 并查集(2)
- 2017暑假集训 div1 连通图(2)
- 暑假集训每日一题0723 (最小生成树)
- 2017暑假集训 div1 最短路(1)
- 2017暑假集训 div1 线段树(2)
- 2017 暑假艾教集训 day12 网络流(最大流 最小割)!
- 2017暑假集训 div1 匹配问题(1)
- 2017暑假集训 div1 最短路(3)
- 2017暑假集训 div1 连通图(1) POJ3694 &&POJ3177
- 2017暑假集训 div1 匹配问题(1)
- sduacm2016级暑假集训 最短路&最小生成树
- 2017暑假集训 div1 DP(1)
- 暑假集训 8.18 数据结构实验之图论六:村村通公路 (最小生成树)
- ACM暑假集训之最小生成树
- 2017暑假集训 div1 并查集(1)
- 2017暑假集训 div1 最短路(2)
- [动态最小生成树 CDQ分治] SnackDown 2017 Online Elimination Round #GQUERY Game Revisited
- [LCT维护最小生成树 || CDQ分治 || 线段树 并查集 dfs树] Codeforces 603E #334 (Div. 1) E. Pastoral Oddities
- 省选集训 airplane 并查集&&最小生成树
- 2017暑假七林集训day7——花翻