poj 2831 次小生成树
给你一幅图,再给你Q个询问
每个询问为id c
即如果将id这条边的边权改为c的话,这条边是否可能是最小生成树中的一条边
做法:先对原图做一次最小生成树,顺便记录一下树中点对间的最长树边是多少
如果id的边权c小于两点间最长的树边,则肯定可以去掉路径上的一条边使得最小生成树总权值更小
View Code
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int inf = ~0u>>2; const int maxn = 1010; bool flag[maxn]; int D[maxn]; int n,map[maxn][maxn]; int mx[maxn][maxn],pre[maxn]; int prime(){ memset(mx,0,sizeof(mx)); int v,ret=0,mi; for(int i=1;i<=n;i++){ flag[i]=0; D[i]=inf; }D[1]=0;flag[1]=1;v=1; for(int k=1;k<n;k++){ for(int i=1;i<=n;i++)if(!flag[i]){ if(map[v][i]<D[i]) D[i]=map[v][i],pre[i]=v; } mi=inf; for(int i=1;i<=n;i++) if(!flag[i]&&D[i]<mi) mi=D[v=i]; for(int i=1;i<=n;i++) if(flag[i]){ mx[v][i]=max(mx[i][pre[v]],D[v]); mx[i][v]=mx[v][i]; } flag[v]=1; ret+=mi; } return ret; } struct Edge{ int s,t,c; Edge(){} Edge(int ss,int tt,int cc):s(ss),t(tt),c(cc){} }edge[maxn*maxn]; int main(){ int m,q,a,b,c,id,num; while(scanf("%d%d%d",&n,&m,&q)!=EOF){ for(int i=1;i<=n;i++){ map[i][i]=0; for(int j=i+1;j<=n;j++){ map[i][j]=map[j][i]=inf; } } for(int i=1;i<=m;i++){ scanf("%d%d%d",&a,&b,&c); edge[i]=Edge(a,b,c); map[b][a]=map[a][b]=min(map[a][b],c); } prime(); while(q--){ scanf("%d%d",&id,&num); printf("%s\n",mx[edge[id].s][edge[id].t]>=num?"Yes":"No"); } } return 0; }