POJ 2831 Can We Build This One?(最小生成树)
2013-12-02 19:33
232 查看
题目链接:http://poj.org/problem?id=2831
题意:
题目大意:给张图,然后问你,如果某边的权值下降为V,那么这个边有无可能在最小生成树中呢?节点数≤1000,边数≤100000,询问数≤100000。
思路:prim。
考虑prim的算法过程:每次加入一个点,并且加入该点的条件是dis[i]是还没加入点的dis[]中最小的。
所以执行prim时,用数组no[]保存某点加入的次序,numm[i]保存第i个加入的点的id
查询边(a,b)时(假设a的加入次序先于b),则枚举no[a]+1 ~ no[b]加入的点的dis[],若存在x<=dis[k],原prim算法过程可被打破,边(a,b)会被选择,
因为该边是当前最佳的边;否则还是原算法过程进行。
1 #include <iostream>
2 #include <cstdio>
3 #include <cmath>
4 #include <cstring>
5 #include <iomanip>
6 using namespace std;
7
8 const int maxd = 1000001;
9 const int N = 1005;
const int M = 1000001;
int map1
, dis
, vis
, no
, numm
;
struct Path
{
int a, b, c;
}p[M];
void prim(int n)
{
int cur;
for(int i=1; i<=n; i++) dis[i] = maxd;
memset(vis, 0, sizeof(vis));
cur = 1; dis[cur] = 0; vis[cur] = 1;
no[cur] = 1; numm[1] = cur;
//找n-1轮
for(int i=2; i<=n; i++)
{
//枚举上一次加入的点与各个点的距离,更新最小距离dis[i]
for(int j=1; j<=n; j++)
{
if(vis[j]==0 && dis[j]>map1[cur][j])
dis[j] = map1[cur][j];
}
//选出最短的边,把该边连接的点加入结果集
int mind = maxd;
for(int j=1; j<=n; j++)
{
if(vis[j]==0 && dis[j]<mind)
{
mind = dis[j];
cur = j;
}
}
vis[cur] = 1;
no[cur] = i;
numm[i] = cur;
}
}
void init(int n)
{
for(int i=1; i<=n; i++)
for(int j=1; j<=n; j++)
map1[i][j] = maxd;
}
int main()
{
int n, m, q, pi, x;
scanf("%d%d%d",&n, &m, &q);
init(n);
for(int i=1; i<=m; i++)
{
scanf("%d%d%d",&p[i].a,&p[i].b,&p[i].c);
if(map1[p[i].a][p[i].b]>p[i].c)
map1[p[i].a][p[i].b] = map1[p[i].b][p[i].a] = p[i].c;
}
//prim走一遍,保存no[],numm[],dis[]
prim(n);
for(int i=1; i<=q; i++)
{
scanf("%d%d",&pi,&x);
int a = no[p[pi].a], b = no[p[pi].b], temp, flag = 0, bno, bnum, sno, snum;
if(a>b){bno = a; bnum = p[pi].a; sno = b; snum = p[pi].b;}
else {bno = b; bnum = p[pi].b; sno = a; snum = p[pi].a;}
//枚举p[pi].a 和 p[pi].b两点之间加入的点
//若x<=dis[],则该边为这轮的最优边,可成为最小生成树中的一边
for(int k=sno+1; k<=bno; k++)
{
if(x<=dis[numm[k]])
{
flag = 1;
break;
}
}
if(flag==1)
printf("Yes\n");
else
printf("No\n");
}
return 0;
}View Code
题意:
题目大意:给张图,然后问你,如果某边的权值下降为V,那么这个边有无可能在最小生成树中呢?节点数≤1000,边数≤100000,询问数≤100000。
思路:prim。
考虑prim的算法过程:每次加入一个点,并且加入该点的条件是dis[i]是还没加入点的dis[]中最小的。
所以执行prim时,用数组no[]保存某点加入的次序,numm[i]保存第i个加入的点的id
查询边(a,b)时(假设a的加入次序先于b),则枚举no[a]+1 ~ no[b]加入的点的dis[],若存在x<=dis[k],原prim算法过程可被打破,边(a,b)会被选择,
因为该边是当前最佳的边;否则还是原算法过程进行。
1 #include <iostream>
2 #include <cstdio>
3 #include <cmath>
4 #include <cstring>
5 #include <iomanip>
6 using namespace std;
7
8 const int maxd = 1000001;
9 const int N = 1005;
const int M = 1000001;
int map1
, dis
, vis
, no
, numm
;
struct Path
{
int a, b, c;
}p[M];
void prim(int n)
{
int cur;
for(int i=1; i<=n; i++) dis[i] = maxd;
memset(vis, 0, sizeof(vis));
cur = 1; dis[cur] = 0; vis[cur] = 1;
no[cur] = 1; numm[1] = cur;
//找n-1轮
for(int i=2; i<=n; i++)
{
//枚举上一次加入的点与各个点的距离,更新最小距离dis[i]
for(int j=1; j<=n; j++)
{
if(vis[j]==0 && dis[j]>map1[cur][j])
dis[j] = map1[cur][j];
}
//选出最短的边,把该边连接的点加入结果集
int mind = maxd;
for(int j=1; j<=n; j++)
{
if(vis[j]==0 && dis[j]<mind)
{
mind = dis[j];
cur = j;
}
}
vis[cur] = 1;
no[cur] = i;
numm[i] = cur;
}
}
void init(int n)
{
for(int i=1; i<=n; i++)
for(int j=1; j<=n; j++)
map1[i][j] = maxd;
}
int main()
{
int n, m, q, pi, x;
scanf("%d%d%d",&n, &m, &q);
init(n);
for(int i=1; i<=m; i++)
{
scanf("%d%d%d",&p[i].a,&p[i].b,&p[i].c);
if(map1[p[i].a][p[i].b]>p[i].c)
map1[p[i].a][p[i].b] = map1[p[i].b][p[i].a] = p[i].c;
}
//prim走一遍,保存no[],numm[],dis[]
prim(n);
for(int i=1; i<=q; i++)
{
scanf("%d%d",&pi,&x);
int a = no[p[pi].a], b = no[p[pi].b], temp, flag = 0, bno, bnum, sno, snum;
if(a>b){bno = a; bnum = p[pi].a; sno = b; snum = p[pi].b;}
else {bno = b; bnum = p[pi].b; sno = a; snum = p[pi].a;}
//枚举p[pi].a 和 p[pi].b两点之间加入的点
//若x<=dis[],则该边为这轮的最优边,可成为最小生成树中的一边
for(int k=sno+1; k<=bno; k++)
{
if(x<=dis[numm[k]])
{
flag = 1;
break;
}
}
if(flag==1)
printf("Yes\n");
else
printf("No\n");
}
return 0;
}View Code
相关文章推荐
- 【POJ 2831】 Can We Build This One?(prim 最小生成树变形)
- POJ_2831_Can We Build This One?【次小生成树】
- POJ 2831 Can We Build This One (Prim+找圈中最大边)
- POJ2831 Can We Build This One?(次小生成树)
- POJ 2831:Can We Build This One?
- poj 2831 Can We Build This One?
- Pku2831 Can We Build This One?(次小生成树)
- uva 1151 - Buy or Build poj 2784 Buy or Build(最小生成树)
- POJ 2784 Buy or Build最小生成树
- uva 1151 - Buy or Build poj 2784 Buy or Build(最小生成树)
- POJ 2784 Buy or Build(二进制枚举 + 最小生成树)
- uva 1151 - Buy or Build poj 2784 Buy or Build(最小生成树)
- POJ 2784 Buy or Build 最小生成树
- Poj(2784),二进制枚举+最小生成树kruskal Buy or Build
- POJ 2784 Buy or Build 最小生成树
- UVA 1151 && POJ 2784 - Buy or Build 最小生成树 二进制枚举
- poj 1258 Agri-Net 最小生成树
- POJ 3522 最小差值生成树(LCT)
- poj 2485Highways(最小生成树 Kruskal)
- poj2395--Out of Hay(最小生成树)