正向做这道题非常困难,可以从逆向开始。
正向破坏边就是逆向加边。建图的时候把所欲破坏的边除去,那么这个图就是最后的图,当遇到破坏边时就加边,即回复到了破坏此条边之前的状态。
这个和食物过期的想法很像(D - Supermarket POJ - 1456),也是一种贪心的策略。
这个题实现起来比那个dp+权值并查集简单的多,主要是用一个map把边作为键,为除掉被破坏的边做准备。
pair 可以作为map的键。
ps:100多行的代码差点一次就过了(pe)
1 #include <iostream> 2 #include <cstring> 3 #include <queue> 4 #include <map> 5 #include <stack> 6 using namespace std; 7 typedef long long ll; 8 const int maxn=10005; 9 ll cnt[maxn];int f[maxn]; 10 struct node{ 11 char s[10]; 12 int a,b; 13 }Q[5*maxn];//不用更新 14 struct edge{ 15 int a,b; 16 }e[maxn*2];//不用更新 17 int n,m,q; 18 map< pair<int,int>,int> M; 19 void read(){ 20 cin>>n; 21 for(int i=0;i<n;i++) 22 cin>>cnt[i]; 23 cin>>m; 24 for(int i=1;i<=m;i++){ 25 int a,b;cin>>a>>b; 26 if(a>b) swap(a,b); 27 e[i].a=a;e[i].b=b; 28 } 29 cin>>q; 30 for(int i=1;i<=q;i++){ 31 cin>>Q[i].s;if(Q[i].s[0]=='q') cin>>Q[i].a; 32 else{ 33 cin>>Q[i].a>>Q[i].b; 34 if(Q[i].a>Q[i].b) swap(Q[i].a,Q[i].b); 35 pair <int,int> P; 36 P=make_pair(Q[i].a,Q[i].b); 37 M[P]=1; 38 } 39 } 40 } 41 void init(){ 42 M.clear(); 43 for(int i=0;i<=n;i++){ 44 f[i]=i;cnt[i]=0; 45 } 46 } 47 48 int find(int x){ 49 if(x!=f[x]) 50 { 51 f[x]=find(f[x]); 52 } 53 return f[x]; 54 } 55 56 void uniont(int a,int b){ 57 int fa=find(a);int fb=find(b); 58 if(cnt[fa]>cnt[fb]) 59 { 60 f[fb]=fa; 61 }else if(cnt[fa]==cnt[fb]){ 62 if(fa<fb) f[fb]=fa; 63 else f[fa]=fb; 64 }else 65 { 66 f[fa]=fb; 67 } 68 } 69 70 void build(){ 71 for(int i=1;i<=m;i++){ 72 pair<int,int> P; 73 P=make_pair(e[i].a,e[i].b); 74 if(M.count(P)) continue; 75 else 76 { 77 uniont(e[i].a,e[i].b); 78 } 79 } 80 } 81 82 void solve(){ 83 stack <ll> ans; 84 for(int i=q;i>=1;i--){ 85 if(Q[i].s[0]=='q') 86 { 87 int a=Q[i].a; 88 int fa=find(a); 89 if(cnt[fa]<=cnt[a]) ans.push(-1); 90 else ans.push(fa); 91 }else 92 { 93 int a=Q[i].a;int b=Q[i].b; 94 uniont(a,b); 95 } 96 } 97 while(!ans.empty()) 98 { 99 cout <<ans.top()<<"\n"; 100 ans.pop(); 101 } 102 } 103 int main(){ 104 init();int cas=1; 105 std::ios::sync_with_stdio(false); 106 while(cin>>n){ 107 if(cas!=1) cout <<"\n"; 108 cas++; 109 init(); 110 for(int i=0;i<n;i++) 111 cin>>cnt[i]; 112 cin>>m; 113 for(int i=1;i<=m;i++){ 114 int a,b;cin>>a>>b; 115 if(a>b) swap(a,b); 116 e[i].a=a;e[i].b=b; 117 } 118 cin>>q; 119 for(int i=1;i<=q;i++){ 120 cin>>Q[i].s; 121 if(Q[i].s[0]=='q') cin>>Q[i].a; 122 else{ 123 cin>>Q[i].a>>Q[i].b; 124 if(Q[i].a>Q[i].b) swap(Q[i].a,Q[i].b); 125 pair <int,int> P; 126 P=make_pair(Q[i].a,Q[i].b); 127 M[P]=1; 128 } 129 } 130 build();solve(); 131 } 132 return 0; 133 }