题目链接:http://poj.org/problem?id=2831
题意:
给你一个图,每条边有边权。
然后有q组询问(i,x),问你如果将第i条边的边权改为x,这条边是否有可能在新的最小生成树中。
题解:
更改边权相当于新添加了一条边。
新边在新MST中的充要条件是:
加入新边后,在原来的MST上形成的环中,有一条旧边的边权>=x。
(因为如果这样的话,新边可以替换掉那条最大的边)
所以可以预处理出 maxn[i][j]:在原来的MST上,任意两点间路径上的最大边权。
dfs即可。
对于每一个新访问到的节点i,枚举每一个已访问过的节点j,那么:
maxn[i][j] = maxn[j][i] = max(maxn[j][fa[i]], v[fa[i]][i])
复杂度O(N^2)。
AC Code:
1 #include <iostream> 2 #include <stdio.h> 3 #include <string.h> 4 #include <algorithm> 5 #include <vector> 6 #define MAX_N 1005 7 #define MAX_M 100005 8 9 using namespace std; 10 11 struct E 12 { 13 int s; 14 int t; 15 int len; 16 E(int _s,int _t,int _len) 17 { 18 s=_s; 19 t=_t; 20 len=_len; 21 } 22 E(){} 23 friend bool operator < (const E &a,const E &b) 24 { 25 return a.len<b.len; 26 } 27 }; 28 29 struct Edge 30 { 31 int dest; 32 int len; 33 Edge(int _dest,int _len) 34 { 35 dest=_dest; 36 len=_len; 37 } 38 Edge(){} 39 }; 40 41 int n,m,q; 42 int s[MAX_M]; 43 int t[MAX_M]; 44 int v[MAX_M]; 45 int par[MAX_N]; 46 int maxn[MAX_N][MAX_N]; 47 bool vis[MAX_N]; 48 vector<E> e; 49 vector<Edge> edge[MAX_N]; 50 51 void read() 52 { 53 scanf("%d%d%d",&n,&m,&q); 54 for(int i=1;i<=m;i++) 55 { 56 scanf("%d%d%d",&s[i],&t[i],&v[i]); 57 e.push_back(E(s[i],t[i],v[i])); 58 } 59 } 60 61 void init_union_find() 62 { 63 for(int i=1;i<=n;i++) 64 { 65 par[i]=i; 66 } 67 } 68 69 int find(int x) 70 { 71 return par[x]==x ? x : par[x]=find(par[x]); 72 } 73 74 void unite(int x,int y) 75 { 76 int px=find(x); 77 int py=find(y); 78 if(px==py) return; 79 par[px]=py; 80 } 81 82 bool same(int x,int y) 83 { 84 return find(x)==find(y); 85 } 86 87 int kruskal() 88 { 89 init_union_find(); 90 sort(e.begin(),e.end()); 91 int cnt=0; 92 int res=0; 93 for(int i=0;i<e.size();i++) 94 { 95 E temp=e[i]; 96 if(!same(temp.s,temp.t)) 97 { 98 cnt++; 99 res+=temp.len; 100 unite(temp.s,temp.t); 101 edge[temp.s].push_back(Edge(temp.t,temp.len)); 102 edge[temp.t].push_back(Edge(temp.s,temp.len)); 103 } 104 } 105 return cnt==n-1 ? res : -1; 106 } 107 108 void dfs(int now) 109 { 110 vis[now]=true; 111 for(int i=0;i<edge[now].size();i++) 112 { 113 Edge temp=edge[now][i]; 114 if(!vis[temp.dest]) 115 { 116 for(int j=1;j<=n;j++) 117 { 118 if(vis[j]) 119 { 120 maxn[j][temp.dest]=maxn[temp.dest][j]=max(maxn[j][now],temp.len); 121 } 122 } 123 dfs(temp.dest); 124 } 125 } 126 } 127 128 void work() 129 { 130 kruskal(); 131 memset(maxn,0,sizeof(maxn)); 132 memset(vis,false,sizeof(vis)); 133 dfs(1); 134 int i,x; 135 while(q--) 136 { 137 scanf("%d%d",&i,&x); 138 if(x<=maxn[s[i]][t[i]]) printf("Yes\n"); 139 else printf("No\n"); 140 } 141 } 142 143 int main() 144 { 145 read(); 146 work(); 147 }