• [bzoj2324][ZJOI2011]营救皮卡丘


    来自FallDream的博客,未经允许,请勿转载,谢谢。


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

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

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

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

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

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

    请你帮助小智设计一个最佳的营救方案吧! n<=150 k<=10

    首先这个数据范围显然是费用流qaq

    然后自己yy了一个建图,把原图拆点,强制他们之间的边流1,然后从S向0连k的边,向每个点的出点连1的边,直接把原图的边扔进去了,轻松wa题,想了想貌似没法保证它们走的顺序....

    所以考虑把两点之间可行的最短路径直接求出来,然后建边,就能保证结果合法了。也就是对于i->j的路径,强制只走小等于j的点,floyd求出之后从i的出点向j的入点连费用是dis[i][j]的边就行了。

    嗯这个强制流1其实就是从一个点的入点向T连流量为1的边,从S向出点连流量为1的边,满足最大流的时候一定满流。如果还不是很清楚可以学习一下带上下界网络流的一套理论。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<queue>
    #define ll long long
    #define S 0
    #define T 303
    #define INF 1000000000
    using namespace std;
    inline ll read()
    {
        ll x = 0 , f = 1; char ch = getchar();
        while(ch < '0' || ch > '9'){ if(ch == '-') f = -1;  ch = getchar();}
        while(ch >= '0' && ch <= '9'){x = x * 10 + ch - '0';ch = getchar();}
        return x * f;
    }
    
    int n,m,k,cnt=1,head[T+5],ans=0,pi=0,d[T+5],dis[155][155];
    bool mark[T+5],inq[T+5];
    deque<int> q;
    struct edge{int to,next,w,c;}e[80005];
    
    inline void ins(int f,int t,int w,int c)
    {
        e[++cnt]=(edge){t,head[f],w,c}; head[f]=cnt;
        e[++cnt]=(edge){f,head[t],0,-c};head[t]=cnt;
    } 
    
    bool modlabel()
    {
        q.push_back(T);
        for(int i=S;i<T;i++)d[i]=INF;d[T]=0;inq[T]=1;
        while(!q.empty())
        {
            int x=q.front();q.pop_front();
            for(int i=head[x];i;i=e[i].next)
                if(e[i^1].w&&d[x]+e[i^1].c<d[e[i].to])
                {
                    d[e[i].to]=d[x]+e[i^1].c;
                    if(!inq[e[i].to])
                    {
                        inq[e[i].to]=1;
                        if(d[e[i].to]<d[q.size()?q.front():0]) q.push_front(e[i].to);
                        else q.push_back(e[i].to);
                    }
                }
            inq[x]=0;
        }
        for(int i=S;i<=T;i++)    
            for(int j=head[i];j;j=e[j].next)
                e[j].c+=d[e[j].to]-d[i];
        return pi+=d[S],d[S]<INF;
    }
    
    int dfs(int x,int f)
    {
        if(x==T) return ans+=pi*f,f;
        int used=0;mark[x]=1;
        for(int i=head[x];i;i=e[i].next)
            if(e[i].w&&!e[i].c&&!mark[e[i].to])
            {
                int w=dfs(e[i].to,min(f-used,e[i].w));
                used+=w;e[i].w-=w;e[i^1].w+=w;
                if(f==used) return f; 
            }
        return used;
    }
    
    int main()
    {
        n=read()+1;m=read();k=read();
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++)
                if(i!=j) dis[i][j]=INF;
        ins(S,1,k,0);
        for(int i=2;i<=n;i++) ins(i+n,T,1,0),ins(S,i,1,0);
        for(int i=1;i<=m;i++)
        {
            int x=read()+1,y=read()+1,c=read();
            dis[x][y]=min(dis[x][y],c);
            dis[y][x]=min(dis[y][x],c);
        }
        for(int k=1;k<=n;k++)
            for(int i=1;i<=n;i++)
                for(int j=1;j<=n;j++)
                    if(dis[i][k]+dis[k][j]<dis[i][j]&&max(i,j)>=k)
                        dis[i][j]=dis[i][k]+dis[k][j];
        for(int i=1;i<=n;i++)
            for(int j=i+1;j<=n;j++)
                if(dis[i][j]<INF) ins(i,j+n,INF,dis[i][j]);
        while(modlabel())
            do memset(mark,0,sizeof(mark));
            while(dfs(S,INF));
        printf("%d
    ",ans);
        return 0;
    }
  • 相关阅读:
    数据结构与算法题目集(中文)7-25 朋友圈 (25分) 并查集
    数据结构与算法题目集(中文)7-24 树种统计 (25分)
    数据结构与算法题目集(中文)7-23 还原二叉树 (25分)
    数据结构与算法题目集(中文)7-22 堆栈模拟队列 (25分)
    数据结构与算法题目集(中文)7-21 求前缀表达式的值 (25分)
    [SDOI2018]反回文串
    ARC 064 F-Rotated Palindromes
    AGC014-F Strange Sorting
    AGC011-E Increasing Numbers
    AGC011-C Squared Graph
  • 原文地址:https://www.cnblogs.com/FallDream/p/bzoj2324.html
Copyright © 2020-2023  润新知