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. }  
  • 相关阅读:
    【C#进阶系列】06 类型和成员基础
    纪中5日T1 1564. 旅游
    纪中17日T1 2321. 方程
    纪中17日T2 2322. capacitor
    纪中10日T1 2313. 动态仙人掌
    纪中14日听课小结 图论 最短路 二分图 差分约束
    一个抓猫的游戏 消遣GAME 持续更新中!
    洛谷P1464 Function  HDU P1579 Function Run Fun
    洛谷P1976 鸡蛋饼
    纪中12日T1 2307. 选择
  • 原文地址:https://www.cnblogs.com/si--nian/p/10449511.html
Copyright © 2011-2022 走看看