HDU 4411 Arrest 最小费用最大流(题意+建图)

news/2024/11/26 2:00:31/

题意:0代表警察局,警局里面有k个警察,然后有1~n个城市,每个城市一个小偷,要想抓到第i个城市的小偷,必须先抓或同时抓一个1~i-1城市的小偷作为铺垫,一个警察一次可以抓多个小偷,一个小偷一次被一个警察抓就可以了,抓完小偷后,必须会到警察局0点,问你所有警察走过的路程和。



想法:显然警察越少越好,先找出城市与城市之间的最短路,floyd就可以。

1.设a到b的边的容量为flow,费用为fee:a->b(flow,fee)

2.点i拆成i和i+n

虚拟一个sink和source,建边:

source->0(k,0),表示可以出动这么多的警察。

0->sink(k,0),表示有的警察可以不使用。

0->i(1,dis[0][i]),表示警察可以走这里。

i->i+n(1,-inf),表示警察来过了这个城市,在这里有两个选择,回家或继续走下去,当然继续走下去的话,这个城市的小偷显然已经被抓住了。

i+n->kk(1,dis[i][k]),其中kk为标号大于i的城市,因为抓下面的小偷,这个走i是前提。

i+n->sink(1,dis[0][i]),表示回家。



还有一个就是特别要注意的地方,我被坑了,这里的inf=100000就够了,这里可以试着算一下,如果过大了比如我一开始定义成了0x7fffffff(就是最大的int),应为在最短路,和流量运算的时候有的数据就已经超出了int的范围,所以就没办法完成代码,导致你找不到错误。


#include<iostream>
#include<cstring>
#include<cstdio>
#include<queue>
#define inf 100000
using namespace std;
const int edges=30000;
const int nodes=250;
int map[nodes][nodes];
int n,m,k,s,t;
int ans;
struct node 
{int v,next;int flow,fee;
}e[edges];
int head[nodes],cnt;
void Init()
{memset(head,-1,sizeof(head));cnt=0;
} 
void add(int a,int b,int c,int d)
{e[cnt].v=b;e[cnt].flow=c;e[cnt].fee=d;e[cnt].next=head[a];head[a]=cnt++;e[cnt].v=a;e[cnt].flow=0;e[cnt].fee=-d;e[cnt].next=head[b];head[b]=cnt++;
} 
class DINIC
{public:int spath(){queue<int>q;while(!q.empty()) q.pop();for(int i=0;i<=n*2+50;i++)dis[i]=inf;memset(vis,0,sizeof(vis));memset(pe,-1,sizeof(pe));vis[s]=1;dis[s]=0;q.push(s);while(!q.empty()){int u=q.front();q.pop();vis[u]=0;for(int i=head[u];i+1;i=e[i].next){int v=e[i].v;if(dis[v]>dis[u]+e[i].fee&&e[i].flow>0){dis[v]=dis[u]+e[i].fee;pe[v]=i;if(!vis[v]){vis[v]=1;q.push(v);}}}}return dis[t]!=inf;}int Min(int a,int b){if(a<b) return a;return b;}int dfs(int u,int flow){int cost=0;if(u==t){ans+=dis[t];return flow;}for(int i=head[u];i+1;i=e[i].next){int v=e[i].v;if(pe[v]==i&&e[i].flow>0){int min=dfs(v,Min(e[i].flow,flow-cost));if(min>0){e[i].flow-=min;e[i^1].flow+=min;cost+=min;if(cost==flow) break;}else pe[v]=-1;}}return cost;}void result(){while(spath()){int kk=dfs(s,inf);}}private:int dis[nodes],vis[nodes],pe[nodes];		
}dinic;
void Input()
{for(int i=0;i<=n;i++)for(int j=0;j<=n;j++){if(i==j) map[i][j]=0;else map[i][j]=inf;}for(int i=1;i<=m;i++){int a,b,c;scanf("%d%d%d",&a,&b,&c);if(a==b) continue;if(map[a][b]<=c) continue;map[a][b]=c;map[b][a]=c;}
}
void pretreatment()
{for(int k=0;k<=n;k++){for(int i=0;i<=n;i++){for(int j=0;j<=n;j++){if(map[i][k]+map[k][j]<map[i][j]){map[i][j]=map[i][k]+map[k][j];}}}}
}
void build_map()
{s=2*n+1;t=2*n+2;add(s,0,k,0);add(0,t,k,0);for(int i=1;i<=n;i++){add(0,i,1,map[0][i]);add(i,i+n,1,-inf);for(int j=i+1;j<=n;j++){add(i+n,j,1,map[i][j]);}add(i+n,t,1,map[0][i]); 	}
}
void treatment()
{ans=0;DINIC *p=&dinic;p->result();printf("%d\n",ans+n*inf);
}
int main()
{while(~scanf("%d%d%d",&n,&m,&k),n+m+k){Init(); Input();pretreatment();build_map();treatment();}return 0;
}


http://www.ppmy.cn/news/370617.html

相关文章

4411 三仙归洞(找规律-周期)

1. 问题描述&#xff1a; 三个倒扣着的不透明小碗排成一排。随机挑选一个小碗&#xff0c;将一个小球置于碗中。然后进行 n 次操作&#xff0c;编号 1∼n。对于第 i 次操作&#xff1a; 如果 i mod 2 1&#xff0c;则操作内容为将位于中间的碗和位于左边的碗交换位置。 如果 …

hdu4411 经典费用里建图

题意: 给以一个无向图,0 - n,警察在0,他们有k个警队,要派一些警队去1--n个城市抓小偷, 问所有吧所有小偷全抓到然后在返回0的最小路径和是多少,当地i个城市被攻击的时候他会通知i-1城市,也就是说要么同时消灭他俩,要么消灭i-1在消灭i; 思路: 经典的费用流建图 ,先…

4411风扇清洗

昨天闲来没事&#xff0c;自己笔记本4411s-425一年半来风扇声音越来越大&#xff0c;于是突然想擦洗风扇。 网上教程只讲解道装内存条和拆解硬盘。4411拆风扇确实很麻烦&#xff0c;如果自己手脚不灵敏的话还是花几十块钱去维修点清洗下&#xff0c;笔记机油那些东西一般人没有…

hdu 4411 Arrest【最小费用流】

题目链接 题意&#xff1a; 给定一个有&#xff08;n1&#xff09;个节点的边权图&#xff0c;其中警察局在0点&#xff0c;其他n个点各有一个黑手党&#xff0c;现在警察局派出k个警察去抓黑手党&#xff0c;并逮捕会警察局&#xff0c;一旦黑手党i被抓&#xff0c;他会向黑…

hdu4411 Arrest 最小费用流

/* 题目描述&#xff1a;有n1个城市&#xff0c;从0到n标号&#xff0c;并给出m条这n 1个城市之间的双向边&#xff0c;1——n每个城市都有一个匪徒&#xff0c;0城市有k名警察&#xff0c;现要求警察 捕捉所有匪徒后并回到0城市的最短路径&#xff0c;其中k名警察可以全部出动…

angular.js:4411 Uncaught Error: [$injector:modulerr]

1、错误描述 angular.js:4411 Uncaught Error: [$injector:modulerr] http://errors.angularjs.org/1.4.6/$injector/modulerr?p0app&p1Error%3A%20%…F%2Fapps.bdimg.com%2Flibs%2Fangular.js%2F1.4.6%2Fangular.min.js%3A19%3A463) 2、错误原因 <!DOCTYPE html> &…

【HDU】4411 Arrest 费用流

传送门&#xff1a;【HDU】4411 Arrest 题目分析&#xff1a;题目的意思一开始没看懂 。。。题意大致为&#xff1a;派出至多K个警队遵守先灭小的再灭老的的原则将N个城市的帮派全端了&#xff08;要灭编号大的必须要先灭编号小的&#xff09;。且一个警队可以一次端多个城市。…

HDU 4411最小费用流

点击打开链接 题意&#xff1a;从0出发&#xff0c;1~N每个城镇有个小偷&#xff0c;我们要把他们全部抓到&#xff0c;我们可以派出k个警察&#xff0c;但是再抓i城镇的小偷之前&#xff0c;i城镇之前的所有城镇的小偷已经被抓了 思路&#xff1a;哪有什么思路,看了网上的题…