• hdu 3376 : Matrix Again【MCMF】


    题目链接

    题意:给定一个n*n的矩阵,找一条路,从左上角到右下角再到左上角,每个点最多经过一次,求路径上的点的权值的最大和。

    将矩阵中每个点拆点,点容量为1,费用为点权值的相反数。每个点向自己右侧和下侧的点连一条容量为1,费用为0的边。左上角为起点,右下角为终点,对起点终点分别额外加条容量为1,费用为0的边,然后跑最大流最小费用。输出费用的相反数即可。

    #include<bits/stdc++.h>
    using namespace std;
    
    const int N=720005;
    const int M=7200050;
    const int INF=0x3f3f3f3f;
    struct Edge
    {
        int to,next;
        int c,f,w;
        Edge(){}
        Edge(int to_,int c_,int f_,int w_,int next_)
        {
            to=to_,c=c_,f=f_,w=w_,next=next_;
        }
    }edge[M<<1];
    int head[N],tot;
    bool inq[N];
    int d[N],p[N],a[N];
    void init()
    {
        memset(head,-1,sizeof(head));
        tot=0;
    }
    void addedge(int u,int v,int c,int w)
    {
        edge[tot]=Edge(v,c,0,w,head[u]), head[u]=tot++;
        edge[tot]=Edge(u,0,0,-w,head[v]),head[v]=tot++;
    }
    bool spfa(int s,int t,int& flow,int& cost)
    {
        memset(d,INF,sizeof(d));
        memset(inq,false,sizeof(inq));
        queue<int> Q;
        d[s]=0,inq[s]=true,a[s]=INF;
        Q.push(s);
        while(!Q.empty())
        {
            int u=Q.front();Q.pop();
            inq[u]=false;
            for(int i=head[u];~i;i=edge[i].next)
            {
                Edge& e=edge[i]; int v=e.to;
                if(e.c>e.f&&d[v]>d[u]+e.w)
                {
                    d[v]=d[u]+e.w,p[v]=i;
                    a[v]=min(a[u],e.c-e.f);
                    if(!inq[e.to]) Q.push(e.to),inq[e.to]=true;
                }
            }
        }
        if(d[t]==INF) return false;
        flow+=a[t],cost+=d[t]*a[t];
        for(int u=t;u!=s;u=edge[p[u]^1].to)
        {
            edge[p[u]].f+=a[t];
            edge[p[u]^1].f-=a[t];
        }
        return true;
    }
    void Mincost(int s,int t,int& flow,int& cost)
    {
        flow=cost=0;
        while(spfa(s,t,flow,cost));
    }
    
    //==============================================
    int n;
    inline int id(int x,int y)
    {
        return x*n+y;
    }
    int main()
    {
        while(~scanf("%d",&n))
        {
            init();
            for(int i=0;i<n;i++)
                for(int j=0;j<n;j++)
                {
                    int temp;
                    scanf("%d",&temp);
                    if(i==0&&j==0||i==n-1&&j==n-1)    addedge(id(i,j),id(i,j)+n*n,1,0);
                    addedge(id(i,j),id(i,j)+n*n,1,-temp);
                    if(i<n-1) addedge(id(i,j)+n*n,id(i+1,j),1,0);
                    if(j<n-1) addedge(id(i,j)+n*n,id(i,j+1),1,0);
                }
            int s=id(0,0),t=id(n-1,n-1)+n*n;
            int flow,cost;
            Mincost(s,t,flow,cost);
            printf("%d
    ",-cost);
        }
    }
  • 相关阅读:
    [JavaScript]继续学习DOM事件模型
    [面试]作答整理一些面试题
    [JavaScript]使用jQuery实现无缝轮播
    [JavaScript]使用CSS + jQuery 实现自动轮播图
    [JavaScript]从DOM到jQuery(2)
    [JavaScript]从DOM到jQuery(1)
    [JavaScript]JavaScript中的函数(2)
    [JavaScript]JavaScript中的函数(1)
    [JavaScript]JavaScript中的Array
    React练习 7 :点击div,显示innerHTML
  • 原文地址:https://www.cnblogs.com/Just--Do--It/p/7678760.html
Copyright © 2020-2023  润新知