逆向并查集

I - Connections in Galaxy War

正向做这道题非常困难,可以从逆向开始。

正向破坏边就是逆向加边。建图的时候把所欲破坏的边除去,那么这个图就是最后的图,当遇到破坏边时就加边,即回复到了破坏此条边之前的状态。

这个和食物过期的想法很像(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 }

猜你喜欢

转载自www.cnblogs.com/Msmw/p/11262568.html