洛谷P3749 [六省联考2017]寿司餐厅

传送门

题解

这几道都是上周llj讲的题,题解也写得十分好了,所以直接贴了几个链接和代码。

//Achen
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<vector>
#include<queue>
#include<cmath>
#include<ctime>
#include<map>
#define For(i,a,b) for(int i=(a);i<=(b);i++)
#define Rep(i,a,b) for(int i=(a);i>=(b);i--)
const int N=200007,inf=0x7fffffff;
typedef long long LL;
using namespace std;
int n,m,s,t,num,D[107][107],id[107][107],ans;
map<int,int>mp;

template<typename T> void read(T &x) {
    T f=1; x=0; char ch=getchar();
    while(ch!=‘-‘&&(ch<‘0‘||ch>‘9‘)) ch=getchar();
    if(ch==‘-‘) f=-1,ch=getchar();
    for(;ch>=‘0‘&&ch<=‘9‘;ch=getchar()) x=x*10+ch-‘0‘; x*=f;
}

struct edge {
    int u,v,fl,cap,nx;
    edge(){}
    edge(int u,int v,int fl,int cap,int nx):u(u),v(v),fl(fl),cap(cap),nx(nx){}
}e[N]; 

int fir[N],cur[N],ecnt=1,p[N];
void add(int u,int v,int cap) {
    e[++ecnt]=edge(u,v,0,cap,fir[u]); fir[u]=ecnt;
    e[++ecnt]=edge(v,u,0,0,fir[v]); fir[v]=ecnt;
}

int calc(int s,int t) {
    int fl=inf;
    for(int i=t;i!=s;i=e[p[i]].u)
        fl=min(fl,e[p[i]].cap-e[p[i]].fl);
    for(int i=t;i!=s;i=e[p[i]].u)
        e[p[i]].fl+=fl,e[p[i]^1].fl-=fl;
    return fl;
} 

int d[N],c[N];
queue<int>que;
void bfs(int s,int t) {
    for(int i=1;i<=n;i++) cur[i]=fir[i],d[i]=n,c[i]=0;
    que.push(t); d[t]=0;
    while(!que.empty()) {
        int x=que.front();
        que.pop();
        for(int i=fir[x];i;i=e[i].nx) if(e[i].cap==0) {
            int y=e[i].v;
            if(d[y]==n) {
                d[y]=d[x]+1;
                que.push(y);
            }
        }
    }
}

int ISAP(int s,int t) {
    int res=0;
    bfs(s,t);
    for(int i=1;i<=n;i++) c[d[i]]++;
    for(int x=s;d[x]<n;) {
        if(x==t) {
            res+=calc(s,t);
            x=s;
        }
        int ok=0;
        for(int &i=cur[x];i;i=e[i].nx)
            if(e[i].fl<e[i].cap&&d[e[i].v]+1==d[x]) {
                p[x=e[i].v]=i; ok=1; break;
            }
        if(!ok) {
            int M=n; cur[x]=fir[x];
            for(int i=fir[x];i;i=e[i].nx) if(e[i].cap>e[i].fl) {
                M=min(M,d[e[i].v]+1);
            }
            if(!(--c[d[x]])) break;
            c[d[x]=M]++;
            if(x!=s) x=e[p[x]].u;
        }
    }
    return res;
}

int main() {
    read(n); read(m);
    s=++num; t=++num; num+=n;
    For(i,1,n) {
        int col; read(col);
        if(!mp[col]) {
            mp[col]=++num;
            add(num,t,m*col*col);
        }
        add(i+2,mp[col],inf);
        add(i+2,t,col);
    }
    For(i,1,n)
        For(j,i,n) {
            read(D[i][j]); id[i][j]=++num;
            if(D[i][j]>=0) {
                add(s,num,D[i][j]);
                ans+=D[i][j];
            }
            else add(num,t,-D[i][j]);
            add(num,i+2,inf);
            add(num,j+2,inf);
        }
    For(i,1,n)
        For(j,i,n) if(i!=j) {
            add(id[i][j],id[i+1][j],inf);
            add(id[i][j],id[i][j-1],inf);
        }
    n=num;
    ans-=ISAP(s,t);
    printf("%d\n",ans);
    return 0;
}

原文地址:https://www.cnblogs.com/Achenchen/p/8604806.html

时间: 2024-07-29 17:56:28

洛谷P3749 [六省联考2017]寿司餐厅的相关文章

P3749 [六省联考2017]寿司餐厅

题意 首先因为每个值只会被算一次且值的个数为\(n^2\)级别的,因此我们可以对每个\(d_{i,j}\)开一个点,之后就可以用最大权闭合子图做. 考虑题目的限制: 1.选择一个区间\([l,r]\)会将\(\sum\limits_{i=l}^{r}\sum\limits_{j=i+1}^rd_{i,j}\)选上: 我们显然不能全部连上,这是\(n^4\)级别的,我们可以只从\(d_{i,j}\)向\(d_{i+1,j}\)和\(d_{i,j-1}\)连边. 2.如果吃过\(c\)种代号为\(x

bzoj千题计划265:bzoj4873: [六省联考2017]寿司餐厅

http://www.lydsy.com/JudgeOnline/problem.php?id=4873 选a必选b,a依赖于b 最大权闭合子图模型 构图: 1.源点 向 正美味度区间 连 流量为 美味度 的边 2.负美味度区间 向 汇点 连 流量为 美味度的绝对值 的边 3.区间[i,j] 向 区间[i+1,j].区间[i,j-1] 连 流量为 inf 的边 4.区间[i,i] 向 寿司i 连 流量为 inf 的边 5.寿司i 向 汇点 连 流量为 寿司代号 的边 6.寿司i 向 它的代号 连

洛谷P3747 [六省联考2017]相逢是问候

传送门 题解 扩展欧拉定理. 线段树维护,已经全改到底了的节点就不管,不然暴力修改下去. //Achen #include<algorithm> #include<iostream> #include<cstring> #include<cstdlib> #include<vector> #include<cstdio> #include<queue> #include<cmath> const int N=5

[六省联考2017]寿司餐厅

题链 这道题长着网络流的数据范围. 最大权闭合子图问题 跑最小割 #include<bits/stdc++.h> #define eho(x) for(int& i=hed[x];~i;i=net[i]) #define Eho(x) for(int i=head[x];~i;i=net[i]) #define N 52607 #define M 3500007 #define NN 1007 #define sight(c) (c<='9'&&c>='0'

[六省联考2017]寿司餐厅(最小割)

题意 题目 思路 由得到的权值不重复可以看出这是一道最大权闭合子图问题 (反正我是没看出来),即最小割 可以看出,如果得到了权值\(d_{l,r}\),可以且必须得到权值\(d_{x,y},(l\leq x \leq y\leq r)\),必须要花费\([l,r]\)这一区间的代价,于是可以得到建图方法 将一个区间看做一个点 \(d_{l,r}>0\),\(ans\) \(+=d_{l,r}\),\(S\)向它连边,边权为\(d_{l,r}\),割掉这条边表示不选择这个值,产生\(d_{l,r}

P3746 [六省联考2017]组合数问题

P3746 [六省联考2017]组合数问题 \(dp_{i,j}\)表示前\(i\)个物品,取的物品模\(k\)等于\(r\),则\(dp_{i,j}=dp_{i-1,(j-1+k)%k}+dp_{i-1,j}\) \(dp_{i,0},dp_{i,1},dp_{i,2}.....dp_{i,k-1}\) \(\Longrightarrow\) \(dp_{i+1,0},dp_{i+1,1},dp_{i+1,2}.....dp_{i+1,k-1}\) 仔细想想,你能构造出矩阵的 #include

[luogu] P3745 [六省联考2017]期末考试 (贪心)

P3745 [六省联考2017]期末考试 题目描述 有 \(n\) 位同学,每位同学都参加了全部的 \(m\) 门课程的期末考试,都在焦急的等待成绩的公布. 第 \(i\) 位同学希望在第 \(t_i\)? 天或之前得知所有课程的成绩.如果在第 \(t_i\) 天,有至少一门课程的成绩没有公布,他就会等待最后公布成绩的课程公布成绩,每等待一天就会产生 \(C\) 不愉快度. 对于第 \(i\) 门课程,按照原本的计划,会在第 \(b_i\)? 天公布成绩. 有如下两种操作可以调整公布成绩的时间:

bzoj千题计划266:bzoj4872: [六省联考2017]分手是祝愿

http://www.lydsy.com/JudgeOnline/problem.php?id=4872 一种最优解是 从大到小灯有亮的就灭掉 最优解是唯一的,且关灯的顺序没有影响 最优解 对每个开关至多操作1次,(连带着的灯的亮灭改变不算) 设最优解 需要操作cnt次,那么就有cnt盏灯是正确的选择 设 f[i] 表示 有i种正确的选择  变为 有i-1种正确的选择 的 期望次数 那么在n盏灯中,有i盏灯操作1次 就可以 减少一次正确选择 有n-i盏灯是错误的选择,选了它还要把它还原,还原它也

[BZOJ4869][六省联考2017]相逢是问候(线段树+扩展欧拉定理)

4869: [Shoi2017]相逢是问候 Time Limit: 40 Sec  Memory Limit: 512 MBSubmit: 1313  Solved: 471[Submit][Status][Discuss] Description Informatikverbindetdichundmich. 信息将你我连结.B君希望以维护一个长度为n的数组,这个数组的下标为从1到n的正整数.一共有m个操作,可以 分为两种:0 l r表示将第l个到第r个数(al,al+1,...,ar)中的每