题目大概一个国家n个城市由m条单向边相连,摧毁每条边都有一个费用。现在你可以选择所给的f个城市中的若干个,每个城市选择后都有一定的价值,但首都1号城市必须到达不了你选择的城市,因为你可能需要摧毁一些边,这样你的获利就是选择城市的价值和减摧毁边的总花费。问,最大的获利是多少以及摧毁哪些边。

如此建容量网络:首都作为源点,原图中单向边的容量设为摧毁边的费用,所有可以选择的城市与汇点相连容量为选择该城市能获得的价值。

这样这个容量网络的S-T割,就能把首都划分到S集合要选择的划分到T集合二者分开,且其最小割就是最小的需要的耗费,耗费由摧毁边的费用和不选择某城市失去的价值组成,最大获利就是f个城市的价值和-最小割。

题目还要求最小割边集的割边,从源点floodfill得到的就是S集合的点,而所有一个端点在S集合另一端点在T集合的边就是最小割边集中的割边。

 #include<cstdio>
#include<cstring>
#include<queue>
#include<algorithm>
using namespace std;
#define INF (1<<30)
#define MAXN 1111
#define MAXM 220000 struct Edge{
int id,v,cap,flow,next;
}edge[MAXM];
int vs,vt,NE,NV;
int head[MAXN]; void addEdge(int id,int u,int v,int cap){
edge[NE].id=id; edge[NE].v=v; edge[NE].cap=cap; edge[NE].flow=;
edge[NE].next=head[u]; head[u]=NE++;
edge[NE].id=id; edge[NE].v=u; edge[NE].cap=; edge[NE].flow=;
edge[NE].next=head[v]; head[v]=NE++;
} int level[MAXN];
int gap[MAXN];
void bfs(){
memset(level,-,sizeof(level));
memset(gap,,sizeof(gap));
level[vt]=;
gap[level[vt]]++;
queue<int> que;
que.push(vt);
while(!que.empty()){
int u=que.front(); que.pop();
for(int i=head[u]; i!=-; i=edge[i].next){
int v=edge[i].v;
if(level[v]!=-) continue;
level[v]=level[u]+;
gap[level[v]]++;
que.push(v);
}
}
} int pre[MAXN];
int cur[MAXN];
int ISAP(){
bfs();
memset(pre,-,sizeof(pre));
memcpy(cur,head,sizeof(head));
int u=pre[vs]=vs,flow=,aug=INF;
gap[]=NV;
while(level[vs]<NV){
bool flag=false;
for(int &i=cur[u]; i!=-; i=edge[i].next){
int v=edge[i].v;
if(edge[i].cap!=edge[i].flow && level[u]==level[v]+){
flag=true;
pre[v]=u;
u=v;
//aug=(aug==-1?edge[i].cap:min(aug,edge[i].cap));
aug=min(aug,edge[i].cap-edge[i].flow);
if(v==vt){
flow+=aug;
for(u=pre[v]; v!=vs; v=u,u=pre[u]){
edge[cur[u]].flow+=aug;
edge[cur[u]^].flow-=aug;
}
//aug=-1;
aug=INF;
}
break;
}
}
if(flag) continue;
int minlevel=NV;
for(int i=head[u]; i!=-; i=edge[i].next){
int v=edge[i].v;
if(edge[i].cap!=edge[i].flow && level[v]<minlevel){
minlevel=level[v];
cur[u]=i;
}
}
if(--gap[level[u]]==) break;
level[u]=minlevel+;
gap[level[u]]++;
u=pre[u];
}
return flow;
} bool vis[MAXN];
void dfs(int u){
vis[u]=;
for(int i=head[u]; i!=-; i=edge[i].next){
int v=edge[i].v;
if(vis[v] || edge[i].cap==edge[i].flow) continue;
dfs(v);
}
}
int ans[];
int main(){
int t,n,m,f,a,b,c;
scanf("%d",&t);
for(int cse=; cse<=t; ++cse){
scanf("%d%d%d",&n,&m,&f);
vs=; vt=; NV=n+; NE=;
memset(head,-,sizeof(head));
for(int i=; i<=m; ++i){
scanf("%d%d%d",&a,&b,&c);
addEdge(i,a,b,c);
}
int tot=;
while(f--){
scanf("%d%d",&a,&b);
tot+=b;
addEdge(,a,vt,b);
}
printf("Case %d: %d\n",cse,tot-ISAP());
memset(vis,,sizeof(vis));
dfs(vs);
tot=;
for(int i=; i<NE; i+=){
int u=edge[i^].v,v=edge[i].v;
if(vis[u] && !vis[v] && edge[i].id) ans[tot++]=edge[i].id;
}
printf("%d",tot);
for(int i=; i<tot; ++i) printf(" %d",ans[i]);
putchar('\n');
}
return ;
}

HDU3251 Being a Hero(最小割)的更多相关文章

  1. HDU 3251 Being a Hero(最小割+输出割边)

    Problem DescriptionYou are the hero who saved your country. As promised, the king will give you some ...

  2. HDU3251 最大流(最小割)

    Being a Hero Time Limit: 20000/10000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Tota ...

  3. Being a Hero (hdu 3251 最小割 好题)

    Being a Hero Time Limit: 20000/10000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) T ...

  4. hdu3251 最小割

    题意: 给n个城市,m条有向边.每条边有权值,如今有些城市能够选择得到.可选的城市有一个价值.可是要满足从1到达不了这些城市,为了满足要求能够去掉一些边,须要花费边的权值,问终于得到的最大价值是多少, ...

  5. [HDU 3521] [最小割] Being a Hero

    题意: 在一个有向图中,有n个点,m条边$n \le 1000 \And \And  m \le 100000$ 每条边有一个破坏的花费,有些点可以被选择并获得对应的金币. 假设一个可以选的点是$x$ ...

  6. 最大流&最小割 - 专题练习

    [例1][hdu5889] - 算法结合(BFS+Dinic) 题意 \(N\)个点\(M\)条路径,每条路径长度为\(1\),敌人从\(M\)节点点要进攻\(1\)节点,敌人总是选择最优路径即最短路 ...

  7. BZOJ 1391: [Ceoi2008]order [最小割]

    1391: [Ceoi2008]order Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 1509  Solved: 460[Submit][Statu ...

  8. BZOJ-2127-happiness(最小割)

    2127: happiness(题解) Time Limit: 51 Sec  Memory Limit: 259 MBSubmit: 1806  Solved: 875 Description 高一 ...

  9. BZOJ-2561-最小生成树 题解(最小割)

    2561: 最小生成树(题解) Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1628  Solved: 786 传送门:http://www.lyd ...

随机推荐

  1. [Effective JavaScript 笔记] 第13条:使用立即调用的函数表达式创建局部作用域

    function wrapElements(a){ var res=[],i,n; for(i=0,n=a.length;i<n;i++){ res[i]=function(){return a ...

  2. 纹理缓存(Texture Cache)

    纹理缓存是将纹理缓存起来方便之后的绘制工作.每一个缓存的图像的大小,颜色和区域范围都是可以被修改的.这些信息都是存储在内存中的,不用在每一次绘制的时候都发送给GPU. CCTextureCache C ...

  3. json串转对象

    // 引入相应的包 //json-lib-2.2-jdk15.jar import net.sf.json.JSONArray;import net.sf.json.JSONObject; 1. // ...

  4. 硬盘安装ubuntu注意事项

    按照教程 http://teliute.org/linux/Ubsetup/jichu3/jichu3.html 安装64位ubuntu的时候,因为64位版本的iso安装包里没有vmlinuz文件,而 ...

  5. linux 下查看某个端口是否被占用

    lsof -i:端口号 转自: http://my.oschina.net/u/193184/blog/146885

  6. 《ASP.NET1200例》ListView控件之修改,删除与添加

    aspx <body> <form id="form1" runat="server"> <div> <asp:Lis ...

  7. C++ virtual descructor

    [代码1]  C++ Code  12345678910111213141516171819202122232425262728293031323334353637383940414243444546 ...

  8. canvas API ,通俗的canvas基础知识(五)

    前几期讲的都是路径图形的绘图,这节我们要讲的是如何在画布上操作图片,因为图形画不了漂亮妹子(画图高手忽略不计),想画美女怎么办?跟我来: 想要在画布中插入一张图片,我们需要的方法是这位大侠: draw ...

  9. WINDOWS xp用户账户怎么没了怎么办?

    这是因为系统的一个默认设置!新建用户会把管理员用户隐藏!只是修改了里面的注册表!在运行(windows徽标+R)里输入“regedit”可以打开注册表编辑器,定位到“HKEY_LOCAL_MACHIN ...

  10. 第一套增删改查(htm+ashx完成)

    1.展示人员列表htm文件: <a href="PersonEditAddNew.ashx?action=addnew">添加</a> </p> ...