首页 > 代码库 > poj 2831 次小生成树模板

poj 2831 次小生成树模板

/*次小生成树
题意:给你一些路径,现在将一部分路径权值减少后问是否可以替代最小生成树里面的边。
解:次小生成树,即将这条边连上,构成一个环
求出任意两点路径之间的除了这条边的最大值,比较这个最大值>=这条边,说明可以替换。
prime算法次小生成树模板
*/
#include<stdio.h>
#include<string.h>
#define N 1100
#define inf 0x3fffffff
int ma[N][N];
int Min(int a,int b) {
return a>b?b:a;
}
int Max(int a,int b) {
return a>b?a:b;
}
struct node {
int u,v,w;
}bian[N*100];
int maxd[N][N],n;
void prime() {
  int i,j,dis[N],vis[N],pre[N],stac[N],top=0;
  memset(maxd,-1,sizeof(maxd));
  for(i=1;i<=n;i++) {//初始化
    dis[i]=ma[1][i];
    pre[i]=1;
  }
  stac[top++]=1;//储存最小生成树的点
  memset(vis,0,sizeof(vis));
  vis[1]=1;
  for(i=1;i<n;i++) {
  int minn=inf,next=1;
  for(j=1;j<=n;j++)
  if(!vis[j]&&minn>dis[j]) {//找到最近的
    minn=dis[j];
    next=j;
  }
  vis[next]=1;
  //printf("%d\n",minn);
  for(j=0;j<top;j++)
    maxd[next][stac[j]]=maxd[stac[j]][next]=Max(minn,maxd[pre[next]][stac[j]]);//当前点与栈里面的点的最大值为minn和他的父节点与其他点的权值最大值
   stac[top++]=next;//加入栈
    for(j=1;j<=n;j++)
    if(!vis[j]&&dis[j]>ma[next][j]) {//更新距离
        pre[j]=next;//与j连接的最近的点即为他的父节点
        dis[j]=ma[next][j];
    }
  }
  return ;
}
int main(){
   int m,i,j,a,b,c,q;
   while(scanf("%d%d%d",&n,&m,&q)!=EOF) {
     for(i=1;i<=n;i++) {
            ma[i][i]=0;
        for(j=i+1;j<=n;j++)
          ma[i][j]=ma[j][i]=inf;
     }
     for(i=0;i<m;i++) {
        scanf("%d%d%d",&a,&b,&c);
        ma[a][b]=ma[b][a]=Min(ma[a][b],c);//
       // printf("%d\n",ma[a][b]);
        bian[i+1].u=a;bian[i+1].v=b;
        bian[i+1].w=c;
     }
     prime();
     while(q--) {
        scanf("%d%d",&a,&b);
      //  printf("%d\n",maxd[bian[a].u][bian[a].v]);
        if(maxd[bian[a].u][bian[a].v]>=b)//比较即可
            printf("Yes\n");
        else
            printf("No\n");
     }
   }
return 0;
}