首页 > 其他分享 >【题解】CF1187G Gang Up

【题解】CF1187G Gang Up

时间:2024-04-11 09:59:22浏览次数:20  
标签:dist int 题解 edge Gang CF1187G lim qu now

【题解】CF1187G Gang Up

题意

给定一个图,有 \(k\) 个人要走到 \(1\) 号节点,问最小花费。

解法

一眼丁真,鉴定为费用流。

考虑到这道题花费会与时间有关,所以 分层图,启动!

按时刻分层,现在分析每个人在第 \(k\) 时刻的动向:

1. 呆着不动。
2. 走到下一个节点。

对于动向 \(1\) ,从时刻 \(k\) 连向 时刻 \(k+1\) ,流量 \(inf\) ,费用 \(0\) 的边。

对于动向 \(2\) ,由于代价 \(a^2\) 有关,所以不能直接建边。

我们分析一下每增加一个人会增加多少费用,也就是考虑怎么把这个平方拆开,直接上公式 \(n^2=\sum\limits_{i=1}^n{2\times i-1}\)。

把每一条原图中的边拆为 \(k\) 条边,对于第 \(i\) 条边,建一条 容量为 \(1\),费用为 \(d\times(2\times-1)\) 的边。

其他边就很好建了,不多赘述 (直接看代码吧)。

代码

注意数组不要开小了。

#include<bits/stdc++.h>
using namespace std;//不过是水题罢了 
const int MX_N=50100,MX_M=5010000,INF=0x3f3f3f3f;
const int tim=120;
struct node{
    int next,to;
    int w,c;
}edge[MX_M<<1];
int head[MX_N]={0},edge_cnt=0;
inline void Add(int x,int y,int w,int c){
    node &i=edge[edge_cnt];
    i.next=head[x],i.w=w,i.c=c,i.to=y;
    head[x]=edge_cnt++;
}
inline void add(int x,int y,int w,int c){
    Add(x,y,w,c),Add(y,x,0,-c);
}
int s=0,t=MX_N-1;
int dist[MX_N]={0},pre[MX_N]={0},lim[MX_N]={0};
bool vis[MX_N]={0};
bool spfa(){
    for(int i=0;i<MX_N;i++)  dist[i]=INF,lim[i]=vis[i]=0;
    queue<int > qu;qu.push(s);vis[s]=1,dist[s]=0,lim[s]=INF;
    while(!qu.empty()){
        int now=qu.front();qu.pop();vis[now]=0;
        for(int i=head[now];~i;i=edge[i].next){
            int to=edge[i].to,w=edge[i].w,c=edge[i].c;
            if(dist[to]>dist[now]+c&&w){
                dist[to]=dist[now]+c;
                pre[to]=i;
                lim[to]=min(lim[now],w);
                if(!vis[to]){
                    qu.push(to);
                    vis[to]=1;
                }
            }
        }
    }
    return lim[t]>0;
}
void EK(int &flow,int &cost){
    flow=cost=0;
    while(spfa()){
        flow+=lim[t];
        cost+=lim[t]*dist[t];
        for(int i=t;i!=s;i=edge[pre[i]^1].to){
            edge[pre[i]].w-=lim[t];
            edge[pre[i]^1].w+=lim[t];
        }
    }
}
int n,m,k,c,d;
inline int has(int now,int ti){
    return ti*n+now;
}
signed main(){
    memset(head,-1,sizeof(head));
    //=======================================
    scanf("%d%d%d%d%d",&n,&m,&k,&c,&d);
    for(int i=1;i<=k;i++){
        int ai;scanf("%d",&ai);
        add(s,has(ai,0),1,0);
    }
    for(int i=1;i<=m;i++){
        int u,v;scanf("%d%d",&u,&v);
        for(int j=0;j<=tim;j++){
            for(int x=1;x<=k;x++){
                add(has(u,j),has(v,j+1),1,d*(x*2-1));
                add(has(v,j),has(u,j+1),1,d*(x*2-1));
            }
        }
    }
    for(int i=1;i<=n;i++){
        for(int j=1;j<=tim;j++){
            add(has(i,j-1),has(i,j),INF,0);
        }
    }
    for(int j=0;j<=tim;j++)  add(has(1,j),t,INF,c*j);
    int flow,cost;EK(flow,cost);
    printf("%d",cost);
    //=======================================
    return 0;
}//CF1187G

求关注,求过。

标签:dist,int,题解,edge,Gang,CF1187G,lim,qu,now
From: https://www.cnblogs.com/DaiFu/p/18128123

相关文章

  • 洛谷 P6692 题解
    洛谷P6692出生点题意简述\(n\)行\(m\)列构成\(nm\)个格点,在其中指定\(k\)个障碍点。每行、每列之间的距离为\(1\),每次任意选取两个非障碍点,计算这两个点的曼哈顿距离,求所有选法的距离之和。分析由容斥原理,答案为「任意两点之间的距离之和」\(-\)「每个障碍点到其他......
  • CF358B Dima and Text Messages 题解
    大家好,我不喜欢string,所以我选择用char来写。题目传送门,但不是洛谷。吐槽一下,这个翻译翻译的并不好,翻译中并没有说明“爱心”是指<3,还是得去自己翻。正文将读入的单词连在一起,并穿插爱心,注意这里首尾都是爱心,需要手动补充。最后将得到的序列与输入的字符串进行比对即可。......
  • 2024年3月电子学会青少年软件编程 中小学生Python编程等级考试一级真题解析(判断题)
    2024年3月Python编程等级考试一级真题解析判断题(共10题,每题2分,共20分)26、turtle画布的坐标系原点是在画布的左上角答案:错考点分析:考查turtle相关知识,turtle画布坐标系是在画布的中点,答案错误27、Python变量名区分大小写,book和BOOK不是同一个变量答案:对考点分析:考查......
  • CF1250A Berstagram 题解
    题面。题意描述的很清楚,这里就不多赘述。思路看题,对于每个\(a_i\),若\(b_j=a_i\),则将\(b_j\)与\(b_{j-1}\)的值调换(若\(j=1\),则序列不变)。一开始想的是最直接的暴力,复杂度为\(O(nm)\),虽然开了三秒的时限,但\(4\times10^{10}\)的数据明显不是三秒钟就能解决的,含恨倒在第......
  • P8791 [蓝桥杯 2022 国 AC] 内存空间 题解
    题面一道比较简单模拟题,但是要分类讨论一.读完题你应该知道的1.输入一共有T+1行,输入含有空格。(处理1)2.对于每一行变量定义的语句,只会出现一种变量类型,type只可能是int或long,只有一个分号。(处理1,处理2)3.统计内存过程中用B做单位,保证一定有输出,但在输出时要换......
  • CF1681C Double Sort 题解
    一道普及-我写了两个半小时题面。需要注意的是,每次交换需要将a和b两个数组同时交换,因此便可以想到唯一可行情况:a,b序列数字间的大小关系必须一致。举个例子2462131317970612在上面的例子中,两个序列中任意\(i\)和\(j\)满足\(a_i\lea_j\)时\(b_i......
  • CF958F1 Lightsabers (easy) 题解
    题面。不好意思,当我看到\(1\len\le100\),\(1\lem\len\)的那一刻,我承认我心动了。题目没翻译,用翻译软件翻译了才看懂。思路依据题意直接模拟即可。这里我用了三层循环来模拟。第一层为\(len\),表示长度;第二层为\(from\),表示出发点,此时需要遍历的区间的终点\(to=from......
  • CF1040B Shashlik Cooking 题解
    题面。看到这道题的第一眼,就想到用分块思想来解决。思路我们知道,当对任意一个\(i\)进行翻转时,区间\([i-k,i+k]\)内的所有元素都会翻转,每次翻转的总个数为\(2\timesk+1\)。因此,我们可以将所有烤串分成长度为\(len=2\timesk+1\)的\(block=n\divlen\)块,用数组\(L......
  • CF158C Cd and pwd commands 题解
    题面。大模拟,但是有坑点。思路依照题意模拟。用一个字符串\(out\)记录在进行了\(i\)次操作后如果要输出输出的东西,字符串\(in\)和\(s\)来分别记录输入的操作及操作类型。由于输出的第一个字符一定是/,所以可以直接将\(out\)的初始化定为out="/"。这样子可以省去......
  • CF875B Sorting the Coins 题解
    题面。算是比较简单的题目了,自己多手出几个样例就可以发现规律了。强烈建议多读几遍题目!!!!思路设0表示硬币朝上,1表示硬币朝下,则第\(0\)次与第\(n\)操作一定输出\(1\)。因为没有可以操作的对象,前者是由于全部硬币朝上,后者是由于全部硬币朝下,即使没有操作也要遍历一遍。注......