zoukankan      html  css  js  c++  java
  • FJWC2019 最短路

    题目描述

    有一张无向图,开始的时候所有边权为1,所有点没有权值,现在给定一个整数k,表示可以将k个点的点权设置为1,求点0到n-1的最短路最长是多少

    Solution

    网络流好题[然而本蒟蒻还是不会][这个建图是真的神仙…]

    最短路最长,最大化最小的问题,考虑二分,我们先二分出一个mid,表示假设最短路最长是mid

    然后建图建mid+1层,将每个点拆成两个点si和ti,从si向ti连一条流量为1的边,表示割掉这条边需要1的代价[割掉了就是+1s]

    为了保证每个点只被选择一次,从这层的si向下一层的ti连一条流量为正无穷的边。然后对于本来图中存在的边<x,y>,从这层的tx向下一层的sy连一条流量为无穷的边

    从这层的sn-1向下一层的sn-1连流量为无穷的边

    如果从第一层的t0到mid+1层的sn-1的最小割<=k 向[mid+1,r]找,否则向[l,mid-1]找

    [本蒟蒻理解这个建图理解了一个晚上x]

    [效果大概长这样?][我画的图还是好丑啊]

    然后建完图跑网络流就可以啦!

    总效率O(能过)

    Code

    1. #include <bits/stdc++.h>  
    2. using namespace std;  
    3. int T,K,N,M;  
    4. const int fish1=101*101*4;  
    5. const int fish2=8*101*101*101;  
    6. vector<int> vec[fish1];  
    7. int cnt,nex[fish2],las[fish2],Arrive[fish2],Flow[fish2];  
    8. int d[fish1];  
    9. void jt(int u,int v,int FF)  
    10. {  
    11.     cnt++;  
    12.     nex[cnt]=las[u];  
    13.     las[u]=cnt;  
    14.     Arrive[cnt]=v;  
    15.     Flow[cnt]=FF;  
    16.     cnt++;  
    17.     nex[cnt]=las[v];  
    18.     las[v]=cnt;  
    19.     Arrive[cnt]=u;  
    20.     Flow[cnt]=0;  
    21. }  
    22. bool BFS()  
    23. {  
    24.     memset(d,0,sizeof(d));  
    25.     d[2]=1;  
    26.     queue<int> qwq;  
    27.     qwq.push(2);  
    28.     while (!qwq.empty())  
    29.     {  
    30.         int R=qwq.front();  
    31.         qwq.pop();  
    32.         for (int i=las[R];i;i=nex[i])  
    33.           {  
    34.             if (Flow[i])  
    35.              {  
    36.                 int RR=Arrive[i];  
    37.                 if (!d[RR])  
    38.                    {  
    39.                    d[RR]=d[R]+1;  
    40.                    qwq.push(RR);  
    41.                   }  
    42.              }  
    43.           }  
    44.     }  
    45.     return d[T]>0;  
    46. }  
    47. int DFS(int Now,int flow)  
    48. {  
    49.     if (!flow) return flow;  
    50.     if (Now==T) return flow;  
    51.     int ans=0;  
    52.     bool b=0;  
    53.     for (int i=las[Now];i;i=nex[i])  
    54.       {  
    55.         if (Flow[i])  
    56.           {  
    57.             int v=Arrive[i];  
    58.             if (d[v]!=d[Now]+1) continue;  
    59.             int tmp=DFS(v,min(Flow[i],flow));  
    60.             if (tmp)  
    61.             {  
    62.                 flow-=tmp;  
    63.                 ans+=tmp;  
    64.                 Flow[i]-=tmp;  
    65.                 Flow[i^1]+=tmp;  
    66.                 b=1;  
    67.                 if (!flow) break;  
    68.             }  
    69.           }  
    70.       }  
    71.       if(!b) d[Now]=-1;  
    72.     return ans;  
    73. }  
    74. int Dinic()  
    75. {  
    76.     int ans=0;  
    77.     while (BFS())  
    78.     {  
    79.         ans+=DFS(2,1e6);  
    80.         if (ans>K) return ans;  
    81.     }  
    82.     return ans;  
    83. }  
    84. bool Check(int Now)  
    85. {  
    86.     cnt=1;  
    87.     memset(las,0,sizeof(las));  
    88.     for (int i=1;i<=Now;i++)  
    89.       {  
    90.         for (int j=N-1;j>1;j--)  
    91.           jt((i-1)*2*N+j*2-1,(i-1)*2*N+j*2,1),jt((i-1)*2*N+j*2-1,i*2*N+j*2,1e6);  
    92.           for (int j=1;j<=N;j++)  
    93.             for (int k=vec[j].size()-1;k>=0;k--)  
    94.                 jt((i-1)*2*N+j*2,i*2*N+(vec[j][k]*2)-1,1e6);  
    95.             jt((i-1)*2*N+N*2-1,i*2*N+(N*2)-1,1e6);  
    96.       }  
    97.     T=(Now+1)*2*N-1;  
    98.     return Dinic()<=K;  
    99. }  
    100. int main()  
    101. {  
    102.     freopen("min.in","r",stdin);  
    103.     freopen("min.out","w",stdout);  
    104.     scanf("%d%d%d",&N,&M,&K);  
    105.     for (int i=1;i<=M;i++)  
    106.       {  
    107.         int u,v;  
    108.         scanf("%d%d",&u,&v);  
    109.         u++;  
    110.         v++;  
    111.         vec[u].push_back(v);  
    112.         vec[v].push_back(u);  
    113.       }  
    114.       int l=1,r=2*N,anss;  
    115.       while (l<=r)  
    116.       {  
    117.         int mid=(l+r)/2;  
    118.         if (Check(mid)) anss=mid,l=mid+1;  
    119.         else r=mid-1;  
    120.       }  
    121.       printf("%d",anss+1);  
    122.     return 0;     
    123. }  
  • 相关阅读:
    一段代码让你了解匿名函数的来龙去脉
    橡皮擦背景色橡皮擦魔术橡皮擦
    flv播放器
    测试面试题01
    java中堆和栈的区别
    经典javaThead 生产者 消费者
    判断一个点是否在三个点组成的三角形内 java 代码 面试经典
    软件项目管理面试题
    java中的位运算
    真正的JDBC java代码
  • 原文地址:https://www.cnblogs.com/si--nian/p/10449511.html
Copyright © 2011-2022 走看看