TopCoder12727 「SRM590Hard」FoxAndCity 最小割离散变量模型

问题描述

一张 \(N\) 个点无向图,边权都为 \(1\) ,添加若干条边,最小化 \(\sum\limits_{1 \le i \le n,i \in N_{+}}{(a_i-b_i)^2}\)。 \(b_i\) 是输入的, \(a_i\) 是 \(1\) 号点到 \(i\) 号点的最短路。

submit


题解

添加边后, \(a_i\) 不会变小。

\(a_i\) 就是离散变量。

原来有边的两个点 \(x,y\) 的最短路长度差值不会超过 \(1\) 。


\(\mathrm{Code}\)

#include<bits/stdc++.h>
using namespace std;

const int INF=0x3f3f3f3f;

//#define local
//#define file

int n,b[47],S,T;
char s[47][47];

int Head[2507],d[2507];
int to[500007],Next[500007],w[500007],tot=1;

void addedge(int x,int y,int z){
    to[++tot]=y,Next[tot]=Head[x],Head[x]=tot,w[tot]=z;
}

void add(int x,int y,int z){
    addedge(x,y,z);addedge(y,x,0);
}

void Init(void){
    scanf("%d",&n);
    for(int i=1;i<=n;i++) scanf("%s",s[i]+1);
    for(int i=1;i<=n;i++) scanf("%d",&b[i]);
}

int dis[2507],sum[2507];
bool vis[2507];
#define pii(x,y) make_pair(x,y)

void dijkstra(){
    memset(dis,0x3f,sizeof(dis));
    priority_queue < pair<int,int> > q;
    dis[1]=0;q.push(pii(0,1));
    while(!q.empty()){
        int x=q.top().second;q.pop();
        if(vis[x]) continue;
        vis[x]=1;
        for(int i=1;i<=n;i++){
            if(s[x][i]=='N') continue;
            if(dis[i]>dis[x]+1){
                dis[i]=dis[x]+1;
                q.push(pii(-dis[i],i));
            }
        }
    }
}

int id(int x,int y){
    return (x-1)*n+y;
}

void debug(void){
    for(int i=2;i<=tot;i+=2){
        printf("-- From %d to %d w = %d \n",to[i^1],to[i],w[i]);
    }
    printf("## S = %d , T = %d\n",S,T);
}

void Graph_build(void){
//  dijkstra();
//  for(int i=1;i<=n;i++) sum[i]=sum[i-1]+dis[i]+1;
    S=n*n+1,T=S+1;
    add(1,T,INF);//错误笔记:1号点最短路为零,为了防止S->1->T不能正常加边,但是1->T还是得加
    for(int i=2;i<=n;i++){
        add(S,id(i,1),INF);
        for(int j=1;j<n;j++){
            int price=(j-b[i])*(j-b[i]);
            add(id(i,j),id(i,j+1),price);
        }
        add(id(i,n),T,INF);
    }
    for(int x=1;x<=n;x++){
        for(int y=1;y<=n;y++){
            if(s[x][y]=='N') continue;
//          int lim=min(dis[x],dis[y]);
            for(int i=1;i<n;i++){
                add(id(x,i+1),id(y,i),INF);
            }
        }
    }
//  debug();
}

bool bfs(void){
    memset(d,0,sizeof(d));
    queue<int>q;q.push(S);d[S]=1;
    while(!q.empty()){
        int x=q.front();q.pop();
        for(int i=Head[x];i;i=Next[i]){
            int y=to[i];
            if(d[y]||!w[i]) continue;
            d[y]=d[x]+1;q.push(y);
            if(y==T) return true;
        }
    }
    return false;
}

int dfs(int x,int flow){
    if(x==T) return flow;
    int rest=flow;
    for(int i=Head[x];i;i=Next[i]){
        int y=to[i];
        if(d[y]!=d[x]+1||!w[i]) continue;
        int k=dfs(y,min(rest,w[i]));
        if(!k) d[y]=0;
        else w[i]-=k,w[i^1]+=k,rest-=k;
    }
    return flow-rest;
}

int Dinic(void){
    int res(0),t;
    while(bfs()){
        while(t=dfs(S,INF)) res+=t;
    }
    return res;
}

int Work(void){
    Graph_build();
    return Dinic();
}

#ifndef local
    class FoxAndCity{
        public:
            int minimalCost(vector<string>str,vector<int>in){
                n=str[0].size();
                for(int i=0;i<n;i++){
                    b[i+1]=in[i];
                    for(int j=0;j<n;j++){
                        s[i+1][j+1]=str[i][j];
                    }
                }
                return Work();
            }
    };
#endif

#ifdef local
    int main(){
        #ifdef file
            freopen("hzlbn.in","r",stdin);
        #endif
        Init();
        printf("%d\n",Work());
        return 0;
    }
#endif

原文地址:https://www.cnblogs.com/liubainian/p/12075795.html

时间: 2024-10-10 01:52:29

TopCoder12727 「SRM590Hard」FoxAndCity 最小割离散变量模型的相关文章

Codechef RIN 「Codechef14DEC」Course Selection 最小割离散变量模型

问题描述 提供中文版本好评,一直以为 Rin 是题目名字... pdf submit 题解 参考了 东营市胜利第一中学姜志豪 的<网络流的一些建模方法>(2016年信息学奥林匹克中国国家队候选队员论文) 读了之后很有感触,这里节选一段话: 最小割模型的本质是将点的集合 \(V\) 划分为两个点集 \(S,T\) ,使得 \(S \in S,T \in T\) ,且 \(S∩T=?\) 之前对最小割中边权为 \(INF\) 的边,一直理解为不允许被割,现在从另一个角度来认识,就是保证这条边所联通

【BZOJ 3232】圈地游戏 二分+SPFA判环/最小割经典模型

最小割经典模型指的是“一堆元素进行选取,对于某个元素的取舍有代价或价值,对于某些对元素,选取后会有额外代价或价值”的经典最小割模型,建立倒三角进行最小割.这个二分是显然的,一开始我也是想到了最小割的那个模型的但是我觉得他会不是一个圈我就否掉了,但是仔细想想的话会发现,如果是这样的话所得到的答案一定小于等于一个圈的答案(浓度),所以我们可定会得到最终答案,所以这样做是可以的,所以说要有宽松得正解的意识(泥沙俱下但沙子不影响我泥).当时我否掉最小割以后就立马去想费用流了,然后想到建图后发现那样建图虽

【LA3487】最小割-经典模型 两种方法

题目链接 题意:A.B两个公司要买一些资源(他们自己买的资源不会重复),一个资源只能卖给一个公司.问最大收益. simple input 部分: 54 1 //买到1就给54元 15 2 33 3 2 4 5//买到4.5就给2元 题解:这道题是很经典的模型题,在这里给出两个方法. 方法一 把每个询问看成一个点,然后A的询问连源点,B的询问连汇点,如果AB间的某个询问有矛盾就在它们中间连一条无限大的边,ans=sum-最小割. // 方法一 把每个询问看成一个点,然后A的询问连源点,B的询问连汇

最小割在模型的应用

Maximize  ∑we - ∑pu 设 du 为u的边权和 s --> u g u-->v v-->u we u-->t g + 2*pu - du ans = (|V|*g - C[s,t])/2

【BZOJ2039】【2009国家集训队】人员雇佣 [最小割]

人员雇佣 Time Limit: 20 Sec  Memory Limit: 259 MB[Submit][Status][Discuss] Description 作为一个富有经营头脑的富翁,小L决定从本国最优秀的经理中雇佣一些来经营自己的公司.这些经理相互之间合作有一个贡献指数,(我们用Ei,j表示i经理对j经理的了解程度),即当经理i和经理j同时被雇佣时,经理i会对经理j做出贡献,使得所赚得的利润增加Ei,j.当然,雇佣每一个经理都需要花费一定的金钱Ai,对于一些经理可能他做出的贡献不值得

【BZOJ 3144】 3144: [Hnoi2013]切糕 (最小割模型)

3144: [Hnoi2013]切糕 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1764  Solved: 965 Description Input 第一行是三个正整数P,Q,R,表示切糕的长P. 宽Q.高R.第二行有一个非负整数D,表示光滑性要求.接下来是R个P行Q列的矩阵,第z个 矩阵的第x行第y列是v(x,y,z) (1≤x≤P, 1≤y≤Q, 1≤z≤R). 100%的数据满足P,Q,R≤40,0≤D≤R,且给出的所有的不和谐值不超

【HDU4859】 海岸线(网络流-最小割)

Problem Description 欢迎来到珠海! 由于土地资源越来越紧张,使得许多海滨城市都只能依靠填海来扩展市区以求发展.作为Z市的决策人,在仔细观察了Z市地图之后,你准备通过填充某些海域来扩展Z市的海岸线到最长,来吸引更多的游客前来旅游度假.为了简化问题,假设地图为一个N*M的格子,其中一些是陆地,一些是可以填充的浅海域,一些是不可填充的深海域.这里定义海岸线的长度为一个联通块陆地(可能包含浅海域填充变为的陆地)的边缘长度,两个格子至少有一个公共边,则视为联通. 值得注意的是,这里Z市

BZOJ 2400 Optimal Marks 最小割

题目大意:给定一个无向图,一些点有权值,其它点的权值可以自己指定,要求指定这些点的权值,使每条边两边的点权异或值之和最小 在此基础上要求点权和最小 首先不考虑点权和最小这个条件 那么我们将每一位分开计算 我们会发现这是一个最小割的模型 令S集为0,T集为1,如果这个点的点权已经指定,则向相应集合连流量为INF的边 每条边的两端点之间连一条流量为1的边 跑最小割就是答案 现在我们将点权考虑进去 将原图每条边的流量扩大10000倍 如果一个点和S没有连边,就从S向这个点连一条流量为1的边 这样如果和

[bzoj1324]Exca王者之剑_最小割

Exca王者之剑 bzoj-1324 题目大意:题目链接. 注释:略. 想法: 最小割经典模型. 所有格子向源点连权值为格子权值的边. 将棋盘黑白染色后白点反转源汇. 如果两个格子相邻那么黑点向白点连$inf$的有向边. 求最小割即可. 开始把所有点的权值都加上,如果被割掉那么就表示这个格子不选. Code: #include <bits/stdc++.h> #define inf 0x3f3f3f3f #define N 100010 using namespace std; queue&l