HDU - 4467 Graph

n个点,m条无向边边有权值,(1 ≤ n,m ≤ 10 5) 。每个点不是黑色就是白色,以0或1区分。

有q组操作(1 ≤ q ≤ 10 5),分为两种:一种是将i号点的颜色改变,一种是给出两个颜色(可以相同),询问图中所有两端是这两种颜色的边的权值之和。

暴力的想法很好想,我们用ans[0] ans[1] ans[2] 分别记录 同黑 、 异色 、同白 的答案,每次改i号点颜色时就遍历所有与i号点相邻的点,以之修改 三个ans ,但这一看就会TLE。

还是用点分块,分轻重点,(见HDU - 4858 项目管理 ) ,i号点是重点,则sum[0][i]维护其到相邻的黑色点的和,sum[1][i]维护白色。

改变颜色时修改ans,轻点爆搜修改,重点根据sum[][i]修改答案。但无论轻重点,都要修改其指向的重点的sum[][i]。

ps : 这题需要把预处理等价的边全部合并,否则还是会TLE。

  1 #include <bits/stdc++.h>
  2 using namespace std;
  3 #define fst first
  4 #define scd second
  5 #define pb(x) push_back((x))
  6 #define mkp(x,y) make_pair((x),(y)) 
  7 #define ist(x) insert((x))
  8 typedef long long ll;
  9 typedef pair<int ,int > pii;
 10 typedef pair<ll ,ll > pll;
 11 typedef vector< int > vi;
 12 ll gcd(ll a,ll b){ return b==0?a:gcd(b,a%b);}
 13 ll qPow(ll a,ll b,ll mod){ ll ret=1ll;while(b){ if(b&1) ret=ret*a%mod;a=a*a%mod;b>>=1;} return ret; }
 14 
 15 const int maxn=1e5+5;
 16 
 17 struct Edge{
 18     int to;
 19     ll weight;
 20     Edge(int v,ll w):to(v),weight(w) {}
 21 };
 22 
 23 struct Bian{
 24     int u;
 25     int v;
 26     ll wei;
 27     Bian(int a,int b,ll c):u(a),v(b),wei(c) {}
 28     Bian(){};
 29 };
 30 ll ans[3];
 31 int degree[maxn];
 32 ll sum[2][maxn];
 33 int col[maxn];
 34 vector< Edge > G[maxn];
 35 Bian bin[maxn];
 36 Bian raw[maxn];
 37 bool heavy[maxn];
 38 int bound;
 39 
 40 void addedge(int u,int v,ll w){
 41     if(!heavy[u]) G[u].pb(Edge(v,w));
 42     else if(heavy[v]) G[u].pb(Edge(v,w)); 
 43 } 
 44 
 45 bool cmp(Bian a,Bian b){
 46     if(a.u!=b.u) return a.u<b.u;
 47     return a.v<b.v;
 48 }
 49 
 50 int main(){
 51     //freopen("data.in","r",stdin);
 52     //freopen("data.out","w",stdout);
 53     int N,M;
 54     int cntcase=1;
 55     while(~scanf("%d%d",&N,&M)){
 56         for(int i=1;i<=N;++i)  scanf("%d",&col[i]);
 57         for(int i=1;i<=N;++i){
 58             degree[i]=0;
 59             sum[0][i]=0ll;sum[1][i]=0ll;
 60             G[i].clear();
 61             heavy[i]=false;
 62         }
 63         ans[0]=ans[1]=ans[2]=0ll;
 64         for(int i=1;i<=M;++i){
 65             int u,v;
 66             ll w;scanf("%d%d%lld",&u,&v,&w);
 67             if(u>v) swap(u,v);
 68             Bian tmp=Bian(u,v,w);
 69             //degree[u]++,degree[v]++;
 70             raw[i] = tmp;
 71         }
 72         sort(raw+1,raw+1+M,cmp);
 73         //for(int i=1;i<=M;++i) printf("%d - %d : %lld\n",raw[i].u,raw[i].v,raw[i].wei);
 74         int cntedge=0;
 75         for(int i=1,j=2;i<=M;i=j){
 76             for(j=i+1;j<=M;++j){
 77                 if(raw[i].u==raw[j].u&&raw[i].v==raw[j].v)
 78                 {
 79                     raw[i].wei+=raw[j].wei;
 80                 }
 81                 else break;    
 82             }
 83             bin[++cntedge]=raw[i];
 84         }
 85         int bound=sqrt(cntedge);
 86         for(int i=1;i<=cntedge;++i){
 87             //printf("%d - %d : %lld\n",bin[i].u,bin[i].v,bin[i].wei);
 88             degree[bin[i].u]++;
 89             degree[bin[i].v]++;
 90         }
 91         for(int i=1;i<=N;++i) if(degree[i]>bound) heavy[i]=true;
 92         for(int i=1;i<=cntedge;++i){
 93             int u,v;
 94             u=bin[i].u,v=bin[i].v;
 95             ll w;
 96             w=bin[i].wei;
 97             addedge(u,v,w);
 98             addedge(v,u,w);
 99             ans[col[u]+col[v]]+=w;
100             if(heavy[v]){
101                 sum[col[u]][v]+=w; 
102             }
103             if(heavy[u]){
104                 sum[col[v]][u]+=w;
105             }
106         }
107         /*
108         for(int i=0;i<3;++i) printf("ans [%d]: %lld\n",i,ans[i]);
109         for(int i=0;i<2;++i){
110             for(int j=1;j<=N;++j){
111                 printf("sum [%d][%d] : %lld\n",i,j,sum[i][j]);
112             }
113         } 
114         */
115         printf("Case %d:\n",cntcase++);
116         int Q;scanf("%d",&Q);
117         for(int i=0;i<Q;++i){
118             char op[10];scanf("%s",op);
119             if(op[0]=='A'){
120                 int aa,bb;scanf("%d%d",&aa,&bb) ;
121                 printf("%I64d\n",ans[aa+bb]);
122             }
123             else{
124                 int u;scanf("%d",&u);
125                 if(!heavy[u]){
126                     for(auto e : G[u]){
127                         int to=e.to;
128                         ll wei=e.weight;
129                         //printf("light %d -> %d : %d\n",u,to,wei);
130                         if(heavy[to]){
131                             sum[col[u]][to]-=wei;
132                             sum[(col[u]^1)][to]+=wei;
133                         }                         
134                         ans[col[u]+col[to]]-=wei;
135                         ans[(col[u]^1)+col[to]]+=wei;
136                         //for(int i=0;i<3;++i) printf("ans [%d]: %lld\n",i,ans[i]);
137                     }
138                     col[u]^=1;
139                 }
140                 else{
141                     ans[col[u]+0]-=sum[0][u];
142                     ans[col[u]+1]-=sum[1][u];
143                     ans[(col[u]^1)+0]+=sum[0][u];
144                     ans[(col[u]^1)+1]+=sum[1][u];
145                     //for(int i=0;i<3;++i) printf("ans [%d]: %lld\n",i,ans[i]);
146                     for(auto e : G[u]){
147                         int to=e.to;
148                         ll wei=e.weight;
149                         //printf("heavy : %d -> %d : %d\n",u,to,wei);
150                         sum[col[u]][to]-=wei;
151                         sum[(col[u]^1)][to]+=wei;
152                     }
153                     col[u]^=1;
154                 }
155                 //for(int i=1;i<=N;++i)  printf(" %d ",col[i]);
156                 //puts("");
157                 //for(int i=0;i<3;++i) printf("ans [%d]: %lld\n",i,ans[i]);
158             }
159         }
160     }
161     return 0;
162 }
View Code

 

 

等一下,既然重点也要搜,为何不“一视同仁”。无论轻重,都用sum[][i]修改,然后搜索修改其指向的点的sum[][i]。

  1 #include <bits/stdc++.h>
  2 using namespace std;
  3 #define fst first
  4 #define scd second
  5 #define pb(x) push_back((x))
  6 #define mkp(x,y) make_pair((x),(y)) 
  7 #define ist(x) insert((x))
  8 typedef long long ll;
  9 typedef pair<int ,int > pii;
 10 typedef pair<ll ,ll > pll;
 11 typedef vector< int > vi;
 12 ll gcd(ll a,ll b){ return b==0?a:gcd(b,a%b);}
 13 ll qPow(ll a,ll b,ll mod){ ll ret=1ll;while(b){ if(b&1) ret=ret*a%mod;a=a*a%mod;b>>=1;} return ret; }
 14 
 15 const int maxn=1e5+5;
 16 
 17 struct Edge{
 18     int to;
 19     ll weight;
 20     Edge(int v,ll w):to(v),weight(w) {}
 21 };
 22 
 23 struct Bian{
 24     int u;
 25     int v;
 26     ll wei;
 27     Bian(int a,int b,ll c):u(a),v(b),wei(c) {}
 28     Bian(){};
 29 };
 30 ll ans[3];
 31 int degree[maxn];
 32 ll sum[2][maxn];
 33 int col[maxn];
 34 vector< Edge > G[maxn];
 35 Bian bin[maxn];
 36 Bian raw[maxn];
 37 bool heavy[maxn];
 38 int bound;
 39 
 40 void addedge(int u,int v,ll w){
 41     if(!heavy[u]) G[u].pb(Edge(v,w));
 42     else if(heavy[v]) G[u].pb(Edge(v,w)); 
 43 } 
 44 
 45 bool cmp(Bian a,Bian b){
 46     if(a.u!=b.u) return a.u<b.u;
 47     return a.v<b.v;
 48 }
 49 
 50 int main(){
 51     //freopen("data.in","r",stdin);
 52     //freopen("data.out","w",stdout);
 53     int N,M;
 54     int cntcase=1;
 55     while(~scanf("%d%d",&N,&M)){
 56         for(int i=1;i<=N;++i)  scanf("%d",&col[i]);
 57         for(int i=1;i<=N;++i){
 58             degree[i]=0;
 59             sum[0][i]=0ll;sum[1][i]=0ll;
 60             G[i].clear();
 61             heavy[i]=false;
 62         }
 63         ans[0]=ans[1]=ans[2]=0ll;
 64         for(int i=1;i<=M;++i){
 65             int u,v;
 66             ll w;scanf("%d%d%lld",&u,&v,&w);
 67             if(u>v) swap(u,v);
 68             Bian tmp=Bian(u,v,w);
 69             //degree[u]++,degree[v]++;
 70             raw[i] = tmp;
 71         }
 72         sort(raw+1,raw+1+M,cmp);
 73         //for(int i=1;i<=M;++i) printf("%d - %d : %lld\n",raw[i].u,raw[i].v,raw[i].wei);
 74         int cntedge=0;
 75         for(int i=1,j=2;i<=M;i=j){
 76             for(j=i+1;j<=M;++j){
 77                 if(raw[i].u==raw[j].u&&raw[i].v==raw[j].v)
 78                 {
 79                     raw[i].wei+=raw[j].wei;
 80                 }
 81                 else break;    
 82             }
 83             bin[++cntedge]=raw[i];
 84         }
 85         int bound=sqrt(cntedge);
 86         for(int i=1;i<=cntedge;++i){
 87             //printf("%d - %d : %lld\n",bin[i].u,bin[i].v,bin[i].wei);
 88             degree[bin[i].u]++;
 89             degree[bin[i].v]++;
 90         }
 91         for(int i=1;i<=N;++i) if(degree[i]>bound) heavy[i]=true;
 92         for(int i=1;i<=cntedge;++i){
 93             int u,v;
 94             u=bin[i].u,v=bin[i].v;
 95             ll w;
 96             w=bin[i].wei;
 97             addedge(u,v,w);
 98             addedge(v,u,w);
 99             ans[col[u]+col[v]]+=w;
100                 sum[col[u]][v]+=w; 
101                 sum[col[v]][u]+=w;
102         }
103         /*
104         for(int i=0;i<3;++i) printf("ans [%d]: %lld\n",i,ans[i]);
105         for(int i=0;i<2;++i){
106             for(int j=1;j<=N;++j){
107                 printf("sum [%d][%d] : %lld\n",i,j,sum[i][j]);
108             }
109         } 
110         */
111         printf("Case %d:\n",cntcase++);
112         int Q;scanf("%d",&Q);
113         for(int i=0;i<Q;++i){
114             char op[10];scanf("%s",op);
115             if(op[0]=='A'){
116                 int aa,bb;scanf("%d%d",&aa,&bb) ;
117                 printf("%I64d\n",ans[aa+bb]);
118             }
119             else{
120                 int u;scanf("%d",&u);
121                 //if(!heavy[u]){
122                     ans[col[u]+0]-=sum[0][u];
123                     ans[col[u]+1]-=sum[1][u];
124                     ans[(col[u]^1)+0]+=sum[0][u];
125                     ans[(col[u]^1)+1]+=sum[1][u];
126                     for(auto e : G[u]){
127                         int to=e.to;
128                         ll wei=e.weight;
129                         //printf("light %d -> %d : %d\n",u,to,wei);
130                             sum[col[u]][to]-=wei;
131                             sum[(col[u]^1)][to]+=wei;
132                         //for(int i=0;i<3;++i) printf("ans [%d]: %lld\n",i,ans[i]);
133                     }
134                     col[u]^=1;
135                 //}
136                 /*
137                 else{
138                     ans[col[u]+0]-=sum[0][u];
139                     ans[col[u]+1]-=sum[1][u];
140                     ans[(col[u]^1)+0]+=sum[0][u];
141                     ans[(col[u]^1)+1]+=sum[1][u];
142                     //for(int i=0;i<3;++i) printf("ans [%d]: %lld\n",i,ans[i]);
143                     for(auto e : G[u]){
144                         int to=e.to;
145                         ll wei=e.weight;
146                         //printf("heavy : %d -> %d : %d\n",u,to,wei);
147                         sum[col[u]][to]-=wei;
148                         sum[(col[u]^1)][to]+=wei;
149                     }
150                     col[u]^=1;
151                 }
152                 */
153                 //for(int i=1;i<=N;++i)  printf(" %d ",col[i]);
154                 //puts("");
155                 //for(int i=0;i<3;++i) printf("ans [%d]: %lld\n",i,ans[i]);
156             }
157         }
158     }
159     return 0;
160 }
View Code

 

想象一下轻重点的连接关系,分块实在是厉害。

 


 

2018.08.13

"一视同仁" 其实还是搞错的,像下面这组数据,先改 重点 再改轻点,会出错。因为修改重点的影响 无法传给 轻点的sum[][i]。

os:能AC纯属数据出的弱吧。

5 4
0 0 0 0 0
1 5 1
2 5 2
3 5 3
4 5 4
11
Asksum 0 0
Asksum 0 1
Asksum 1 1
Change 5
Asksum 0 0
Asksum 0 1
Asksum 1 1
Change 1
Asksum 0 0
Asksum 0 1
Asksum 1 1

还是老老实实 轻点爆搜修改,重点用sum[][i]改吧。

时刻谨记 : 轻点影响轻重点 ,重点只影响重点。

posted on 2018-08-02 23:50  Emiya_Kiritsugu  阅读(233)  评论(0编辑  收藏  举报

导航