Being a Hero (hdu 3251 最小割 好题)
Being a Hero
Time Limit: 20000/10000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 1211 Accepted Submission(s): 381
Special Judge
But don't get too excited. The cities you take should NOT be reachable from the capital -- the king does not want to accidentally enter your area. In order to satisfy this condition, you have to destroy some roads. What's worse, you have to pay for that --
each road is associated with some positive cost. That is, your final income is the total value of the cities you take, minus the total cost of destroyed roads.
Note that each road is a unidirectional, i.e only one direction is available. Some cities are reserved for the king, so you cannot take any of them even if they're unreachable from the capital. The capital city is always the city number 1.
can take. Cities are numbered 1 to n. Each of the following m lines contains three integers u, v, w, denoting a road from city u to city v, with cost w. Each of the following f lines contains two integers u and w, denoting an available city u, with value w.
1 to m in the same order they appear in the input. If there are more than one solution, any one will do.
2
4 4 2
1 2 2
1 3 3
3 2 4
2 4 1
2 3
4 4
4 4 2
1 2 2
1 3 3
3 2 1
2 4 1
2 3
4 4
Case 1: 3
1 4
Case 2: 4
2 1 3
pid=3259" target="_blank">3259
pid=3258" target="_blank">3258
pid=3257" target="_blank">3257
3256 3255题意:n个点m条边的有向图,每条边有破坏话花费,如今国王在城市1,要分配给英雄一些城市。分配的原则是:仅仅能在规定的f个城市中选若干个。这f个城市每一个都有一个获利。被选择的城市要与国王所在的城市1隔离,所以选定后要花费一些费用来破坏边。问最后获利的最大值是多少,而且输出要破坏的边的序号。
思路:这个题拿到手之后非常久没有思路。由于图上既有获利又有花费,不知道怎么建图。无奈仅仅好求助网上神牛。
加入汇点T,原图上的单向边依次建边,容量为花费,同意选择的f个点向汇点T连边。容量为点上权值。
跑一遍最小割得到花费值cost,然后用总的能获得利润(就是f个点的权值之和)减去cost就是答案。那么如何确定哪条边是割边呢?从源点S在残留网络中dfs遍历能走到的点。那么这些点就是属于S集,其它剩下的点就属于T集了。然后推断边的两个点所属的集合。假设属于不同的集合那么这条边就是割边。
这样建边就全然转换成费用了,对于原图上的边假设被割到,那么这条边就是要破坏的,对于和汇点相连的边假设被割到。那么这个城市就是不能选的,最后最小割就是最小费用,感觉这样非常巧妙。
代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <string>
#include <map>
#include <stack>
#include <vector>
#include <set>
#include <queue>
#pragma comment (linker,"/STACK:102400000,102400000")
#define pi acos(-1.0)
#define eps 1e-6
#define lson rt<<1,l,mid
#define rson rt<<1|1,mid+1,r
#define FRE(i,a,b) for(i = a; i <= b; i++)
#define FREE(i,a,b) for(i = a; i >= b; i--)
#define FRL(i,a,b) for(i = a; i < b; i++)
#define FRLL(i,a,b) for(i = a; i > b; i--)
#define mem(t, v) memset ((t) , v, sizeof(t))
#define sf(n) scanf("%d", &n)
#define sff(a,b) scanf("%d %d", &a, &b)
#define sfff(a,b,c) scanf("%d %d %d", &a, &b, &c)
#define pf printf
#define DBG pf("Hi\n")
typedef long long ll;
using namespace std; #define INF 0x3f3f3f3f
#define mod 1000000009
const int maxn = 1005;
const int MAXN = 2005;
const int MAXM = 200010;
const int N = 1005; int n,m,f; struct Edge
{
int to,next,cap,flow;
}edge[MAXM]; int tol;
int head[MAXN];
int gap[MAXN],dep[MAXN],pre[MAXN],cur[MAXN]; void init()
{
tol=0;
memset(head,-1,sizeof(head));
} //加边,单向图三个參数。双向图四个參数
void addedge(int u,int v,int w,int rw=0)
{
edge[tol].to=v; edge[tol].cap=w; edge[tol].next=head[u];
edge[tol].flow=0; head[u]=tol++;
edge[tol].to=u; edge[tol].cap=rw; edge[tol].next=head[v];
edge[tol].flow=0; head[v]=tol++;
} //输入參数:起点。终点,点的总数
//点的编号没有影响。仅仅要输入点的总数
int sap(int start,int end,int N)
{
memset(gap,0,sizeof(gap));
memset(dep,0,sizeof(dep));
memcpy(cur,head,sizeof(head));
int u=start;
pre[u]=-1;
gap[0]=N;
int ans=0;
while (dep[start]<N)
{
if (u==end)
{
int Min=INF;
for (int i=pre[u];i!=-1;i=pre[edge[i^1].to])
if (Min>edge[i].cap-edge[i].flow)
Min=edge[i].cap-edge[i].flow;
for (int i=pre[u];i!=-1;i=pre[edge[i^1].to])
{
edge[i].flow+=Min;
edge[i^1].flow-=Min;
}
u=start;
ans+=Min;
continue;
}
bool flag=false;
int v;
for (int i=cur[u];i!=-1;i=edge[i].next)
{
v=edge[i].to;
if (edge[i].cap-edge[i].flow && dep[v]+1==dep[u])
{
flag=true;
cur[u]=pre[v]=i;
break;
}
}
if (flag)
{
u=v;
continue;
}
int Min=N;
for (int i=head[u];i!=-1;i=edge[i].next)
if (edge[i].cap-edge[i].flow && dep[edge[i].to]<Min)
{
Min=dep[edge[i].to];
cur[u]=i;
}
gap[dep[u]]--;
if (!gap[dep[u]]) return ans;
dep[u]=Min+1;
gap[dep[u]]++;
if (u!=start) u=edge[pre[u]^1].to;
}
return ans;
} bool vis[MAXN];
int out[MAXN]; void dfs(int u)
{
if (vis[u]) return ;
vis[u]=true;
for (int i=head[u];~i;i=edge[i].next)
{
int v=edge[i].to;
if (edge[i].cap-edge[i].flow>0)
dfs(v);
}
return ;
} int main()
{
#ifndef ONLINE_JUDGE
freopen("C:/Users/lyf/Desktop/IN.txt","r",stdin);
#endif
int i,j,t,u,v,w,cas=0;
sf(t);
while (t--)
{
init();
sfff(n,m,f);
for (i=0;i<m;i++)
{
sfff(u,v,w);
addedge(u,v,w);
}
int T=0,all=0;
for (i=0;i<f;i++)
{
sff(u,w);
addedge(u,T,w);
all+=w;
}
printf("Case %d: %d\n",++cas,all-sap(1,T,n+1));
mem(vis,false);
dfs(1);
int cnt=0;
for (i=0;i<2*m;i+=2)
{
if (vis[edge[i^1].to]&&!vis[edge[i].to])
out[cnt++]=i/2;
}
printf("%d",cnt);
for (i=0;i<cnt;i++)
pf(" %d",out[i]+1);
pf("\n");
}
return 0;
}
Being a Hero (hdu 3251 最小割 好题)的更多相关文章
- [HDU 3521] [最小割] Being a Hero
题意: 在一个有向图中,有n个点,m条边$n \le 1000 \And \And m \le 100000$ 每条边有一个破坏的花费,有些点可以被选择并获得对应的金币. 假设一个可以选的点是$x$ ...
- hdu 4289(最小割)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4289 思路:求最小花费,最小割应用,将点权转化为边权,拆点,(i,i+n)之间连边,容量为在城市i的花 ...
- HDU 5889 Barricade(最短路+最小割水题)
Barricade Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others) Total ...
- hdu 5076 最小割灵活运用
这意味着更复杂的问题,关键的事实被抽象出来:每个点,能够赋予既有的值(挑两个一.需要选择,设定ai,bi). 寻找所有和最大.有条件:如果两个点同时满足: 1,:二进制只是有一个不同之处. 2:中的 ...
- Game HDU - 3657(最小割)
Game Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submis ...
- hdu 1565 最小割
黑白染色,源指向白,黑指向汇,容量都是方格中数的大小,相邻的格子白指向黑,容量为oo,然后求一次最小割. 这个割是一个简单割,如果只选择不在割中的点,那么一种割就和一个选数方案一一对应,割的大小就是不 ...
- hdu 3657 最小割的活用 / 奇偶方格取数类经典题 /最小割
题意:方格取数,如果取了相邻的数,那么要付出一定代价.(代价为2*(X&Y))(开始用费用流,敲升级版3820,跪...) 建图: 对于相邻问题,经典方法:奇偶建立二分图.对于相邻两点连边2 ...
- hdu 3657 最小割(牛逼!!!!)总算理解了
<strong></strong> 转载:http://blog.csdn.net/me4546/article/details/6662959 加颜色的太棒了!!! 在网上看 ...
- hdu 3691最小割将一个图分成两部分
转载地址:http://blog.csdn.net/xdu_truth/article/details/8104721 题意:题给出一个无向图和一个源点,让你求从这个点出发到某个点最大流的最小值.由最 ...
随机推荐
- python_字符串类型
1.在python中用单引号' ',双引号'' '',三引号''' ''' 标注字符串类型. >>> name = "Alex Li" #双引号 >> ...
- Ubuntu16.04 搭建svn
1.安装SVN 安装前先更新一下 sudo apt-get update 接下来安装 sudo apt-get install subversion 2.创建SVN版本库 1.创建home下的svn文 ...
- 大数据学习——mapreduce学习topN问题
求每一个订单中成交金额最大的那一笔 top1 数据 Order_0000001,Pdt_01,222.8 Order_0000001,Pdt_05,25.8 Order_0000002,Pdt_05 ...
- [luoguP1352] 没有上司的舞会(DP)
传送门 树上的dp,从底向上dp就行. 设dp[u][0]表示不选节点 u 的最大值,dp[u][1]表示选节点 u 的最大值. 则状态转移方程为: dp[u][0] = ∑max(dp[v][1], ...
- 洛谷P1258 小车问题
题目描述 甲.乙两人同时从A地出发要尽快同时赶到B地.出发时A地有一辆小车,可是这辆小车除了驾驶员外只能带一人.已知甲.乙两人的步行速度一样,且小于车的速度.问:怎样利用小车才能使两人尽快同时到达. ...
- Open Judge 3339 List
3339:List 总时间限制: 4000ms 内存限制: 65536kB 描述 写一个程序完成以下命令:new id ——新建一个指定编号为id的序列(id<10000)add id nu ...
- HDU 5521 Meeting【最短路】
今天旁观了Angry_Newbie的模拟区域赛(2015shenyang) 倒着看最先看的M题,很明显的最短路问题,在我看懂的时候他们已经开始敲B了. 后来听说D过了很多人.. D题一看是个博弈,给了 ...
- HDU 1024 【DP】
题意: 给n个数将其分成连续的m组,使得这些组的数加和最大,组与组之间可以空数. /* dp[i][j]表示将前j个数分成i个组最大值 状态转移方程是: dp[i][j]=max(dp[i-1][0. ...
- Android远程服务
一.远程服务主要代码 1.IService.aidl package com.shz.remoteservice; interface IService { String getTicketInfoB ...
- 去哪网实习总结:easyui在JavaWeb中的使用,以datagrid为例(JavaWeb)
本来是以做数据挖掘的目的进去哪网的,结构却成了系统开发. . . 只是还是比較认真的做了三个月.老师非常认同我的工作态度和成果.. . 实习立即就要结束了,总结一下几点之前没有注意过的变成习惯和问题, ...