1. 程式人生 > >POJ 2831 Can We Build This One:次小生成樹【N^2預處理】

POJ 2831 Can We Build This One:次小生成樹【N^2預處理】

efi tar int pan false 處理 eof log clas

題目鏈接: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 }

POJ 2831 Can We Build This One:次小生成樹【N^2預處理】