(2016北京集训十三)【xsy1532】网络战争 - 最小割树+树上倍增+KD树

题解:

好题!!

这题似乎能上我代码长度记录的前五?

调试时间长度应该也能上前五QAQ

首先题目要求的明显就是最小割,当然在整个森林上求Q次最小割肯定是会GG的,所以我们需要一个能快速求最小割的算法——最小割树。

最小割树,也叫分治最小割,就是通过预处理把原本的图缩成一颗树,树上两个节点路径上的最小边权就是它们的最小割,这个用树上倍增可以随便维护。

大概思想就是先求一次最小割,把划分出的S和T两个点集继续求最小割,向下分治然后连边缩点。

这题先对每个州预处理最小割树,州和州之间用KD树求出距离最近的点,然后查询的时候用树上倍增跳。

分别写出来就好了qwq

所以这就是道码农题,码码码码码码

有必要说一下时间复杂度是O(玄学),这个时间复杂度严格来说是过不了的,但是数据随机,每个州和大的森林联通块的期望大小不大,所以不知道为什么就过了。。。

PS:我没写KD树,写了个排序剪枝,也是玄学就过了。。。

代码:

  1 #include<algorithm>
  2 #include<iostream>
  3 #include<cstring>
  4 #include<cstdio>
  5 #include<cmath>
  6 #include<queue>
  7 #include<map>
  8 #define inf 2147483647
  9 #define eps 1e-9
 10 using namespace std;
 11 typedef long long ll;
 12 struct node{
 13     int x,y,id;
 14     friend bool operator <(node a,node b){
 15         if(a.x!=b.x)return a.x<b.x;
 16         if(a.y!=b.y)return a.y<b.y;
 17         return a.id<b.id;
 18     }
 19 }p[300001],pp[300001];
 20 int N,n,m,q,u,v,w,ta,tb,qa,qb,cnt=0,bcc=0,num[300001],fr[300001],pts[300001],blg[300001];
 21 bool used[300001];
 22 namespace capitals{
 23     struct edge{
 24         int v,w,next;
 25     }a[300001];
 26     int tot=0,head[300001],dep[300001],fa[300001][20],minn[300001][20];
 27     void add(int u,int v,int w){
 28         a[++tot].v=v;
 29         a[tot].w=w;
 30         a[tot].next=head[u];
 31         head[u]=tot;
 32     }
 33     void dfs(int u,int ff,int dpt,int d){
 34         blg[u]=bcc;
 35         dep[u]=dpt;
 36         fa[u][0]=ff;
 37         minn[u][0]=d;
 38         for(int i=1;i<=19;i++){
 39             fa[u][i]=fa[fa[u][i-1]][i-1];
 40             minn[u][i]=min(minn[u][i-1],minn[fa[u][i-1]][i-1]);
 41         }
 42         for(int tmp=head[u];tmp!=-1;tmp=a[tmp].next){
 43             int v=a[tmp].v;
 44             if(v!=ff){
 45                 dfs(v,u,dpt+1,a[tmp].w);
 46             }
 47         }
 48     }
 49     int query(int u,int v){
 50         if(dep[u]<dep[v])swap(u,v);
 51         int ret=inf;
 52         for(int i=19;i>=0;i--){
 53             if(dep[fa[u][i]]>=dep[v]){
 54                 ret=min(ret,minn[u][i]);
 55                 u=fa[u][i];
 56             }
 57         }
 58         if(u==v)return ret;
 59         for(int i=19;i>=0;i--){
 60             if(fa[u][i]!=fa[v][i]){
 61                 ret=min(ret,min(minn[u][i],minn[v][i]));
 62                 u=fa[u][i],v=fa[v][i];
 63             }
 64         }
 65         return min(ret,min(minn[u][0],minn[v][0]));
 66     }
 67 }
 68 namespace dinic{
 69     struct edge{
 70         int v,w,next;
 71     }a[300001];
 72     int n,m,vs,vt,tot=0,dep[300001],s[300001],flw[300001],nmd[300001],head[300001];
 73     queue<int>q;
 74     void add(int u,int v,int w){
 75         a[++tot].v=v;
 76         a[tot].w=w;
 77         a[tot].next=head[u];
 78         head[u]=tot;
 79     }
 80     void clr(){
 81         //memset(head,-1,sizeof(head));
 82         for(int i=1;i<=n;i++)head[i]=-1;
 83         tot=1;
 84     }
 85     bool bfs(){
 86         for(int i=1;i<=n;i++)dep[i]=0;
 87         while(!q.empty())q.pop();
 88         q.push(vs);
 89         dep[vs]=1;
 90         while(!q.empty()){
 91             int u=q.front();
 92             q.pop();
 93             for(int tmp=head[u];tmp!=-1;tmp=a[tmp].next){
 94                 int v=a[tmp].v;
 95                 if(!dep[v]&&a[tmp].w){
 96                     dep[v]=dep[u]+1;
 97                     if(v==vt)return true;
 98                     q.push(v);
 99                 }
100             }
101         }
102         return false;
103     }
104     int dfs(int u,int num){
105         if(u==vt||!num)return num;
106         int ans=0;
107         for(int tmp=head[u];tmp!=-1;tmp=a[tmp].next){
108             int v=a[tmp].v;
109             if(dep[v]==dep[u]+1&&a[tmp].w){
110                 int f=dfs(v,min(num,a[tmp].w));
111                 if(f){
112                     a[tmp].w-=f;
113                     a[tmp^1].w+=f;
114                     ans+=f;
115                     num-=f;
116                     if(!num)break;
117                 }
118             }
119         }
120         if(!ans)dep[u]=-1;
121         return ans;
122     }
123     void build_mincost(int l,int r){
124         if(r<=l)return;
125         int dnc=0,ls=l,rs=r;
126         vs=nmd[l],vt=nmd[r];
127         for(int i=2;i<=tot+1;i++)a[i].w=flw[i/2];
128         while(bfs())dnc+=dfs(vs,inf);
129         for(int i=l;i<=r;i++){
130             if(dep[nmd[i]])s[ls++]=nmd[i];
131             else s[rs--]=nmd[i];
132         }
133         for(int i=l;i<=r;i++)nmd[i]=s[i];
134         capitals::add(vs+cnt,vt+cnt,dnc);
135         capitals::add(vt+cnt,vs+cnt,dnc);
136         //printf("Added %d->%d Flow=%d\n",vs+cnt,vt+cnt,dnc);
137         build_mincost(l,ls-1);
138         build_mincost(rs+1,r);
139     }
140 }
141 int dis(node a,node b){
142     return (a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y);
143 }
144 void solve(int k){
145     int ans=inf,now=0;
146     for(int i=k+1;i<=N;i++){
147         if((pp[i].x-pp[k].x)*(pp[i].x-pp[k].x)>ans)break;
148         int ds=dis(pp[i],pp[k]);
149         if(ds<ans){
150             ans=ds;
151             now=i;
152         }else if(ds==ans&&pp[i].id<pp[now].id)now=i;
153     }
154     for(int i=k-1;i;i--){
155         if((pp[i].x-pp[k].x)*(pp[i].x-pp[k].x)>ans)break;
156         int ds=dis(pp[i],pp[k]);
157         if(ds<ans){
158             ans=ds;
159             now=i;
160         }else if(ds==ans&&pp[i].id<pp[now].id)now=i;;
161     }
162     fr[pp[k].id]=pp[now].id;
163 }
164 int main(){
165     memset(capitals::head,-1,sizeof(capitals::head));
166     scanf("%d",&N);
167     for(int i=1;i<=N;i++){
168         scanf("%d%d%d%d%d",&p[i].x,&p[i].y,&num[i],&n,&m);
169         p[i].id=i;
170         pp[i]=p[i];
171         pts[i]=cnt+1;
172         dinic::n=n;
173         dinic::m=m;
174         dinic::clr();
175         for(int j=1;j<=n;j++)dinic::nmd[j]=j;
176         for(int j=1;j<=m;j++){
177             scanf("%d%d%d",&u,&v,&w);
178             dinic::add(u,v,w);
179             dinic::add(v,u,w);
180             dinic::flw[j]=w;
181         }
182         dinic::build_mincost(1,n);
183         cnt+=n;
184     }
185     sort(pp+1,pp+N+1);
186     for(int i=1;i<=N;i++)solve(i);
187     for(int i=1;i<=N;i++){
188         if(used[i])continue;
189         if(i==fr[fr[i]]){
190             used[fr[i]]=true;
191             capitals::add(pts[i],pts[fr[i]],num[i]+num[fr[i]]);
192             capitals::add(pts[fr[i]],pts[i],num[i]+num[fr[i]]);
193             //printf("Added %d->%d Flow=%d\n",pts[fr[i]],pts[i],num[i]+num[fr[i]]);
194         }else{
195             capitals::add(pts[i],pts[fr[i]],num[i]);
196             capitals::add(pts[fr[i]],pts[i],num[i]);
197             //printf("Added %d->%d Flow=%d\n",pts[fr[i]],pts[i],num[i]);
198         }
199     }
200     for(int i=1;i<=N;i++){
201         if(!blg[pts[i]]){
202             bcc++;
203             capitals::dfs(pts[i],0,1,inf);
204         }
205     }
206     scanf("%d",&q);
207     for(int i=1;i<=q;i++){
208         scanf("%d%d%d%d",&ta,&tb,&qa,&qb);
209         qa=pts[ta]+qa-1;
210         qb=pts[tb]+qb-1;
211         if(blg[qa]!=blg[qb])puts("0");
212         else printf("%d\n",capitals::query(qa,qb));
213     }
214     return 0;
215 }
posted @ 2018-09-24 20:44  DCDCBigBig  阅读(221)  评论(0编辑  收藏  举报