【JZOJ 3749】【Srm590】Fox And City

HOWARLI發表於2017-04-17

Description

A long time ago, 有一個國家有n 座從0 到n-1編號的城市。城市0 是首都。國家道路網路形成了一個無向連通圖。換句話說:某些對城市被雙向通行的道路所連線。

對於每座城市,可以從城市出發經過一系列連續的道路到達首都。(當兩條道路需要在城市外相交時,相交處總是會有一座橋樑,因此城市外並沒有路口。)

你會獲得一個用於描述道路網路的字元矩陣linked。對於每個i 和j,當城市i 和城市j 已由一條道路直接連通時linked[i][j] 為‘Y’ ,否則為‘N’ 。

兩個城市間的距離為從一個城市到達另一個城市所需通過的道路的最小數目。居住在首都以外的市民通常都對他們與首都之間的距離不爽。因此你會獲得一個n 個元素的陣列want。對於每個i,want[i] 是城市i 與首都之間的市民

期望距離。

福克斯· 夏爾正在負責建造新的道路。每個新道路必須雙向且連線兩座城市。一旦所有的新道路落成,市民們會計算他們對最終道路網路的不爽值:

對於每個i:令real[i] 為從城市i 到達首都的新距離。那麼城市i 的市民增加的對國家的不爽值為(want[i]-real[i])^2。

計算並回答夏爾建造一些(可能是零)新道路之後新增不爽值之和的最小值。

Solution

題目的要求就是求出一個序列,使得在滿足:有直接連邊的兩數差不超過1;的情況下,使得代價最小。

這題的正解很暴力,用最小割;
首先對於每個點,構出n個點,第i點表當這個點數值為i的情況,有以下幾種連線:
1. 第i-1個向第i個連權值為(當這個點值為i時的代價),第1個被S連,最後一個向T連正無窮;
2. 第i個向第i-1個連正無窮;(因為在最後的圖中,如果i能被S流到,那麼i-1也一定要能夠)
3. 對於在原圖中有直接連邊的a,b,因為它們的值差不能超過1,所以當最後的值是Va>Vb

V_a>V_b
時,對於所有的k,如果a的第k個點能被S流到,那麼b的k-1及以下的都要被S流到,所有a的第k個向b的第k-1個連正無窮;當Va<Vb
V_a<V_b
則反之。

連完以後直接跑最小割出來的值就是Ans了

Code

#include <iostream>
#include <cstdio>
#include <cstdlib>
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define efo(i,q) for(int i=A[q];i;i=B[i][0])
#define BH(i,q) ((i)*n-n+(q)+1)
#define sqr(q) ((q)*(q))
using namespace std;
const int N=3000,INF=1e9;
int read(int &n)
{
    char ch=' ';int q=0,w=1;
    for(;(ch!='-')&&((ch<'0')||(ch>'9'));ch=getchar());
    if(ch=='-')w=-1,ch=getchar();
    for(;ch>='0' && ch<='9';ch=getchar())q=q*10+ch-48;n=q*w;return n;
}
int m,n,ans,S,T;
int B[N*N][3],A[N],B0=1;
int Hv[N],H[N];
void link(int q,int w,int e,int e1)
{
    if(e==0&&e1==0)return;
    B[++B0][0]=A[q],A[q]=B0,B[B0][1]=w,B[B0][2]=e;
    B[++B0][0]=A[w],A[w]=B0,B[B0][1]=q,B[B0][2]=e1;
}
int aug(int q,int e)
{
    if(q==T)return e;
    int mi=T+2;
    efo(i,q)if(B[i][2])
    {
        if(H[B[i][1]]+1==H[q])
        {
            int t=aug(B[i][1],min(e,B[i][2]));
            if(t)
            {
                B[i][2]-=t;
                B[i^1][2]+=t;
                return t;
            }
        }
        mi=min(mi,H[B[i][1]]);
        if(H[S]>T+1)return 0;
    }
    if(!(--Hv[H[q]]))H[S]=T+3;
    Hv[H[q]=mi+1]++;
    return 0;
}
int main()
{
    freopen("fox.in","r",stdin);
    freopen("fox.out","w",stdout);
    int q,w;
    while(scanf("%d",&n)!=EOF)
    {
        B0=1;
        S=0;T=n*n+1;
        fo(i,S,T)A[i]=0;
        link(BH(1,n-1),T,INF,0);
        fo(i,2,n)link(S,BH(i,0),INF,0),link(BH(i,n-1),T,INF,0);
        fo(i,1,n)
        {
            char ch=' ';
            while(ch!='Y'&&ch!='N')ch=getchar();
            fo(j,1,n)
            {
                if(ch=='Y')
                {
                    fo(k,1,n-1)
                        link(BH(i,k),BH(j,k-1),INF,0);
                }
                ch=getchar();
            }
        }
        fo(i,1,n)
        {
            read(q);
            fo(k,0,n-2)link(BH(i,k),BH(i,k+1),(i==1?INF:sqr(q-k-1)),0);
        }
        ans=0;
        fo(i,S,T+10)H[i]=Hv[i]=0;
        Hv[0]=T+1;
        while(H[S]<T+2)ans+=aug(S,INF);
        printf("%d\n",ans);
    }
    return 0;
}

相關文章