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 题意:题给出一个无向图和一个源点,让你求从这个点出发到某个点最大流的最小值.由最 ...
随机推荐
- Feedback on Ch5 paper based on CFD-RANS
It is encouraging that you took the initiative to write this journal manuscript, but it needs a lot ...
- Counting Kangaroos is Fun 求最少可见袋鼠数
Description There are n kangaroos with pockets. Each kangaroo has a size (integer number). A kangaro ...
- 【BZOJ 2761】 不重复数字 (哈希算法)
链接 http://www.lydsy.com/JudgeOnline/problem.php?id=2761 Description 给出N个数,要求把其中重复的去掉,只保留第一次出现的数. 例如, ...
- Nowcoder 106 C.Professional Manager(统计并查集的个数)
题意: 给出四种操作: 1. 合并u,v两棵树 2. 从u所在的集合中删除u 3. 询问u所在集合有多少颗树 4. 询问 u,v是否在同一个集合 分析: 对于删除操作, 只要新开一个点代替原来的点即可 ...
- 在不是modelAttribute的情况下,如何保存页面输入值的方法(多行遍历)
<c:forEach var="prdRelInfo" items="${goodRelPrdList}" varStatus="s" ...
- Java学习关于集合框架的基础接口--Collection接口
集合框架(Collection Framework)是Java最强大的子系统之一,位于java.util 包中.集合框架是一个复杂的接口与和类层次,提供了管理对象组的最新技术.Java集合框架标准 ...
- 【字符串+BFS】Problem 7. James Bond
https://www.bnuoj.com/v3/external/gym/101241.pdf [题意] 给定n个字符串,大小写敏感 定义一个操作:选择任意m个串首尾相连组成一个新串 问是否存在一个 ...
- Flask处理前端POST过来的JSON数据
POST JSON数据的JS代码: $.ajax({ url:'http://127.0.0.1:5000/calc', type : 'post', dataType:'json', headers ...
- 最大和(codevs 1648)
题目描述 Description N个数围成一圈,要求从中选择若干个连续的数(注意每个数最多只能选一次)加起来,问能形成的最大的和. 输入描述 Input Description 第一行输入N,表示数 ...
- [NOIP1998] 普及组
三连击 题目描述 将1,2,…,9共9个数分成三组,分别组成三个三位数,且使这三个三位数构成1:2:3的比例,试求出所有满足条件的三个三位数. 输入输出格式 输入格式: 木有输入 输出格式: 若干行, ...