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

Leohh發表於2017-12-20

題目連結: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 }

 

相關文章