• 洛谷P2754 [CTSC1999]家园


    题目链接:https://www.luogu.org/problemnew/show/P2754

    知识点:  最大流

    解题思路:

      先用 (DFS) 判断是否无解。

      从时刻 (0) 开始枚举答案,从飞船此刻的位置往下一时刻的位置连边,容量为飞船的载客量,然后在上一刻的残量网络的基础上跑 (sap),将最大流累加起来,当最大流的累加和大于或等于 (k) 时,便可得出答案。

      对于同一个位置的不同时刻,要用不同的点代表,并且把他们按照时间的先后顺序连起来,容量为 (INF);对于代表地球的任一时刻的点,从源点连边指向它们,容量为 (INF);对于代表月亮的任一时刻的点,连一条指向源点的边,容量也为 (INF)。

    AC代码:

      1 #include <bits/stdc++.h>
      2 using namespace std;
      3 
      4 const int MAXN=10000;
      5 const int MAXM=10000;
      6 const int INF=0x3f3f3f3f;
      7 struct Edge{
      8     int to,Next,cap,flow;
      9 }edge[MAXM];
     10 int tol;
     11 int head[MAXN];
     12 int gap[MAXN],dep[MAXN],cur[MAXN];
     13 void init(){
     14     tol=0;
     15     memset(head,-1,sizeof(head));
     16 }
     17 void addedge(int u,int v,int w,int rw=0){
     18     edge[tol].to=v; edge[tol].cap=w; edge[tol].flow=0;
     19     edge[tol].Next=head[u]; head[u]=tol++;
     20     edge[tol].to=u; edge[tol].cap=rw; edge[tol].flow=0;
     21     edge[tol].Next=head[v]; head[v]=tol++;
     22 }
     23 int Q[MAXN];
     24 void BFS(int start,int ends){
     25     memset(dep,-1,sizeof(dep));
     26     memset(gap,0,sizeof(gap));
     27     gap[0]=1;
     28     int fronts=0,rear=0;
     29     dep[ends]=0;
     30     Q[rear++]=ends;
     31     while(fronts!=rear){
     32         int u=Q[fronts++];
     33         for(int i=head[u];i!=-1;i=edge[i].Next){
     34             int v=edge[i].to;
     35             if(dep[v]!=-1)  continue;
     36             Q[rear++]=v;
     37             dep[v]=dep[u]+1;
     38             gap[dep[v]]++;
     39         }
     40     }
     41 }
     42 int S[MAXN];
     43 int sap(int start,int ends,int N){
     44     BFS(start,ends);
     45     memcpy(cur,head,sizeof(head));
     46     int top=0;
     47     int u=start;
     48     int ans=0;
     49     while(dep[start]<N){
     50         if(u==ends){
     51             int Min=INF;
     52             int inser;
     53             for(int i=0;i<top;i++){
     54                 if(Min>edge[S[i]].cap-edge[S[i]].flow){
     55                     Min=edge[S[i]].cap-edge[S[i]].flow;
     56                     inser=i;
     57                 }
     58             }
     59             for(int i=0;i<top;i++){
     60                 edge[S[i]].flow+=Min;
     61                 edge[S[i]^1].flow-=Min;
     62             }
     63             ans+=Min;
     64             top=inser;
     65             u=edge[S[top]^1].to;
     66             continue;
     67         }
     68         bool flag=false;
     69         int v;
     70         for(int i=cur[u];i!=-1;i=edge[i].Next){
     71             v=edge[i].to;
     72             if(edge[i].cap-edge[i].flow && dep[v]+1==dep[u]){
     73                 flag=true;
     74                 cur[u]=i;
     75                 break;
     76             }
     77         }
     78         if(flag){
     79             S[top++]=cur[u];
     80             u=v;
     81             continue;
     82         }
     83         int Min=N;
     84         for(int i=head[u];i!=-1;i=edge[i].Next){
     85             if(edge[i].cap-edge[i].flow && dep[edge[i].to]<Min){
     86                 Min=dep[edge[i].to];
     87                 cur[u]=i;
     88             }
     89         }
     90         gap[dep[u]]--;
     91         if(!gap[dep[u]])    return ans;
     92         dep[u]=Min+1;
     93         gap[dep[u]]++;
     94         if(u!=start)    u=edge[S[--top]^1].to;
     95     }
     96     return ans;
     97 }
     98 
     99 int h[25],p[25];
    100 int r[25][15];
    101 vector<int> G[20];
    102 bool viss[20];
    103 void dfs(int rt,int moon){
    104     viss[rt]=true;
    105     if(rt==moon)    return;
    106     for(int i=0;i<G[rt].size();i++){
    107         int v=G[rt][i];
    108         if(!viss[v]) dfs(v,moon);
    109     }
    110 }
    111 
    112 int main(){
    113     int n1,m1,k1;
    114     scanf("%d%d%d",&n1,&m1,&k1);
    115     for(int i=0;i<m1;i++){
    116         scanf("%d%d",&h[i],&p[i]);
    117         for(int j=0;j<p[i];j++){
    118             scanf("%d",&r[i][j]);
    119             if(r[i][j]==-1)
    120                 r[i][j]=n1+1;
    121         }
    122         for(int j=0;j<p[i];j++){
    123             int u=r[i][j],v=r[i][(j+1)%p[i]];
    124             G[u].push_back(v);
    125         }
    126     }
    127     dfs(0,n1+1);
    128     if(!viss[n1+1]){
    129         puts("0");
    130         return 0;
    131     }
    132     init();
    133     int s=0,t=1;
    134     int now=0,add=2,had=0;
    135     int tot=2+(n1+2)*2;
    136     addedge(s,add,INF);
    137     addedge(add+n1+1,t,INF);
    138     while(1){
    139         for(int i=0;i<m1;i++){
    140             int u=r[i][now%p[i]]+add,v=r[i][(now+1)%p[i]]+add+n1+2;
    141             addedge(u,v,h[i]);
    142         }
    143         for(int i=0;i<n1+2;i++)
    144             addedge(i+add,i+add+n1+2,INF);
    145         addedge(add+n1+1+n1+2,t,INF);
    146         had+=sap(s,t,tot);
    147         if(had>=k1){
    148             printf("%d
    ",now+1);
    149             return 0;
    150         }
    151         now++;
    152         tot+=n1+2;
    153         add+=n1+2;
    154     }
    155 }
    “这些年我一直提醒自己一件事情,千万不要自己感动自己。大部分人看似的努力,不过是愚蠢导致的。什么熬夜看书到天亮,连续几天只睡几小时,多久没放假了,如果这些东西也值得夸耀,那么富士康流水线上任何一个人都比你努力多了。人难免天生有自怜的情绪,唯有时刻保持清醒,才能看清真正的价值在哪里。”
  • 相关阅读:
    arthas命令ognl视频演示
    arthas命令sc和sm视频演示
    混合Java函数和Groovy闭包
    Mock System.in和检查System.out
    arthas命令logger动态修改日志级别--视频演示
    删除List中null的N种方法--最后放大招
    ovs安装教程
    win10中安装与配置maven
    win10系统中按顺序安装jdk、tomcat
    win10系统中按顺序安装jdk、tomcat
  • 原文地址:https://www.cnblogs.com/Blogggggg/p/9320617.html
Copyright © 2020-2023  润新知