• [费用流][floyd] Luogu P4542 营救比卡丘


    题目描述

    皮卡丘被火箭队用邪恶的计谋抢走了!这三个坏家伙还给小智留下了赤果果的挑衅!为了皮卡丘,也为了正义,小智和他的朋友们义不容辞的踏上了营救皮卡丘的道路。

    火箭队一共有NN个据点,据点之间存在MM条双向道路。据点分别从11到NN标号。小智一行KK人从真新镇出发,营救被困在NN号据点的皮卡丘。为了方便起见,我们将真新镇视为00号据点,一开始KK个人都在00号点。

    由于火箭队的重重布防,要想摧毁KK号据点,必须按照顺序先摧毁11到K-1K1号据点,并且,如果K-1K1号据点没有被摧毁,由于防御的连锁性,小智一行任何一个人进入据点KK,都会被发现,并产生严重后果。因此,在K-1K1号据点被摧毁之前,任何人是不能够经过KK号据点的。

    为了简化问题,我们忽略战斗环节,小智一行任何一个人经过KK号据点即认为KK号据点被摧毁。被摧毁的据点依然是可以被经过的。

    KK个人是可以分头行动的,只要有任何一个人在K-1K1号据点被摧毁之后,经过KK号据点,KK号据点就被摧毁了。显然的,只要NN号据点被摧毁,皮卡丘就得救了。

    野外的道路是不安全的,因此小智一行希望在摧毁NN号据点救出皮卡丘的同时,使得KK个人所经过的道路的长度总和最少。

    请你帮助小智设计一个最佳的营救方案吧!

    题解

    • 因为路径之间两两不能相交,所以每个点至少且至多要被进入一次,除n以外的点做多出去一次
    • 那么我们可以把一个点拆成两个,一个入点一个出点,1-n的出点向汇点连边,源点向1到n-1的出点连边,然后源点向0连流量为k的边

    代码

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cstring>
     4 #include <queue>
     5 #define inf 0x3f3f3f3f
     6 using namespace std; 
     7 const int N=160;
     8 int n,m,k,cnt,s,t,head[N*2],dis[N*2],f[N][N],vis[N*2],pre[N*2],ans;
     9 struct edge{int from,to,c,w,next;}e[N*N*20];
    10 queue<int> Q;
    11 void insert(int u,int v,int c,int w)
    12 {
    13     e[++cnt].from=u,e[cnt].to=v,e[cnt].c=c,e[cnt].w=w,e[cnt].next=head[u],head[u]=cnt;
    14     e[++cnt].from=v,e[cnt].to=u,e[cnt].c=0,e[cnt].w=-w,e[cnt].next=head[v],head[v]=cnt;
    15 }
    16 bool spfa()
    17 {
    18     for (int i=0;i<=t;i++) dis[i]=inf;
    19     Q.push(s),dis[s]=0,vis[s]=1;
    20     while (!Q.empty())
    21     {
    22         int u=Q.front();Q.pop();
    23         for (int i=head[u];i;i=e[i].next)
    24             if (e[i].c&&dis[u]+e[i].w<dis[e[i].to])
    25             {
    26                 dis[e[i].to]=dis[u]+e[i].w,pre[e[i].to]=i;
    27                 if (!vis[e[i].to]) vis[e[i].to]=1,Q.push(e[i].to);
    28             }
    29         vis[u]=0;
    30     }
    31     return dis[t]!=inf;
    32 }
    33 void mcf()
    34 {
    35     ans+=dis[t]; int x=t;
    36     while (pre[x]) e[pre[x]].c--,e[pre[x]^1].c++,x=e[pre[x]].from;
    37 }
    38 int main()
    39 {
    40     scanf("%d%d%d",&n,&m,&k);
    41     s=n*2+1,t=n*2+2,cnt=1,insert(s,0,k,0);
    42     for (int i=1;i<=n;i++) insert(i,t,1,0);
    43     for (int i=1;i<n;i++) insert(s,i+n,1,0);
    44     memset(f,inf,sizeof(f));
    45     for (int i=0;i<=n;i++) f[i][i]=0;
    46     for (int i=1,x,y,z;i<=m;i++) scanf("%d%d%d",&x,&y,&z),f[x][y]=f[y][x]=min(f[x][y],z);
    47     for (int k=0;k<=n;k++) for (int i=0;i<=n;i++) for (int j=0;j<=n;j++) if (k<i||k<j) f[i][j]=min(f[i][j],f[i][k]+f[k][j]);
    48     for (int i=0;i<n;i++) for (int j=i+1;j<=n;j++) if (f[i][j]<inf) insert(i?i+n:i,j,1,f[i][j]);
    49     while (spfa()) mcf(); printf("%d",ans);
    50 }
  • 相关阅读:
    百度脑图
    Bootstrap入门
    Tomcat热部署的三种方式
    There is a chart instance already initialized on the dom!警告
    Ubuntu14.04设置开机自启动脚本
    PRM路径规划算法
    A*算法
    V-rep学习笔记:串口操作
    V-rep学习笔记:机器人路径规划2
    V-rep学习笔记:机器人逆运动学解算
  • 原文地址:https://www.cnblogs.com/Comfortable/p/11233537.html
Copyright © 2020-2023  润新知