• (2016北京集训十三)【xsy1532】网络战争


    题解:

    好题!!

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

    调试时间长度应该也能上前五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
    ",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
    ",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
    ",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
    ",capitals::query(qa,qb));
    213     }
    214     return 0;
    215 }
  • 相关阅读:
    『转』MySQL存储过程语法例子
    搭建mysql cluster
    C++ typedef 两种用法
    C++符号重载
    C++ int const 和 const int 的区别
    C++ 结构和类的区别
    正式开始jQuery源码的学习
    c# in deep 之Lambda表达式于LINQ表达式结合后令人惊叹的简洁(2)
    c# in deep 之Lambda表达式
    一道有意思的导论问题
  • 原文地址:https://www.cnblogs.com/dcdcbigbig/p/9696619.html
Copyright © 2020-2023  润新知