- 浏览: 378351 次
- 性别:
- 来自: 杭州
文章分类
最新评论
-
wsyzyrxp:
非常感谢 兄弟 帮了我大忙
[opengl]弹簧质点法模拟柔性布料以及椭球碰撞的opengl实现 -
mingdry0304:
[opengl]彩色立方体旋转 -
tyfengyu:
我刚刚更改的代码加上了标准差stdVal,故recoMat应该 ...
[python]用python实现的pca算法 -
tyfengyu:
python的pca代码有2处错误:1.finalData = ...
[python]用python实现的pca算法 -
暴风雪:
McFlurry 写道前排(凑字数)!擦你怎么摸来这里的
诈尸总结
大致题义:
给出n条鱼之间相互攻击的关系以及每条鱼的能量值,每条鱼只能攻击或者被攻击最多一次(也就是被攻击之后无法攻击别人,或者攻击别人之后无法被攻击)。一次攻击行为产能为这两条鱼能量值的异或值。求总能量值最大是多少。
大致思路:
用KM算法,把每条鱼拆做两个点,连别求最大匹配的思路很容易想到,代码如下。
#include<cstdio> #include<iostream> #include<cstring> using namespace std; const int nMax=204; const int mMax=1005; const int inf=1<<29; int map[nMax][nMax]; int lx[nMax],ly[nMax]; int mapch[nMax]; int stack[nMax]; bool sy[nMax],sx[nMax]; int n,m,e,cnt; int find (int u){ int v,t; sx[u]=1; for(v=1;v<=m;v++){ if(sy[v]) continue; t=lx[u]+ly[v]-map[u][v]; if(t==0){ sy[v]=1; if(mapch[v]==-1||find(mapch[v])){ mapch[v]=u; return 1; } } else if(t<stack[v]) stack[v]=t; } return 0; } int KM(){ int i,j,k,d,sum=0; cnt=0; for(i=1;i<=m;i++) ly[i]=0; memset(mapch,-1,sizeof(mapch)); for(i=1;i<=n;i++){ lx[i]=-inf; for(j=1;j<=m;j++) if(map[i][j]>lx[i]) lx[i]=map[i][j]; } for(i=1;i<=n;i++){ for(j=1;j<=m;j++) stack[j]=inf; while(1){ for(k=1;k<=m;k++) sy[k]=0; for(k=1;k<=n;k++) sx[k]=0; if(find(i)) break; d=inf; for(k=1;k<=m;k++) if(!sy[k]&&stack[k]<d) d=stack[k]; for(k=1;k<=n;k++) if(sx[k]) lx[k]-=d; for(k=1;k<=m;k++) if(sy[k]) ly[k]+=d; else stack[k]-=d; } } for(i=1;i<=m;i++) if(mapch[i]!=-1&&map[mapch[i]][i]!=-inf){ sum+=map[mapch[i]][i]; } return sum; } char str[nMax]; int val[nMax]; int main(){ int i,j,a; while(scanf("%d",&n)&&n){ m=n; memset(map,0,sizeof(map)); for(i=1;i<=n;i++)scanf("%d",&val[i]); for(i=1;i<=n;i++){ scanf("%s",str+1); for(j=1;j<=n;j++){ if(str[j]=='1'){ map[i][j]=val[i]^val[j]; } } } printf("%d\n",KM()); } return 0; }
起初我用的是费用流,但是却wa了。连边构图时我很容易就能联想到,对每条鱼a,我们都将其拆做两点a和a‘。从原点向a连边,容量是1,费用是0。从a’向汇点连边,容量是1,费用是0。如果a攻击b则连接a->b'容量为1,费用为这两条鱼能产生的产能。求出费用流即可。但是却wa了……囧。后来看了 AekdyCoin 才明白。因为求出费用流的时候,流量必须是最大 。也就是这道题中得到最大产能的时候,图中的流量未必是最大。如下图
我们希望的答案是9,但是费用流得到的结果是2!因为当费用是9的时候,当前网络还未达到最大流。
为了解决以上问题,对于每个a,我们可以连接一条边a->t,使得总流量等于鱼的数量。接下来求出最小费用即可。
#include<cstdio> #include<cstring> #include<iostream> using namespace std; const int inf=99999999; const int nMax=3000; const int mMax=2000000; struct{ int u,v, cap, cost, next, re; }edge[mMax]; int ans,maxf; int k,edgeHead[nMax]; int que[nMax],pre[nMax],dis[nMax]; bool vis[nMax],flag; int K; void addEdge(int u,int v,int ca,int co){////始点 终点 流量 花费 edge[k].v=v; edge[k].cap=ca; edge[k].cost=co; edge[k].next=edgeHead[u]; edge[k].re=k + 1; edgeHead[u]=k ++; edge[k].v=u; edge[k].cap=0; edge[k].cost=-co; edge[k].next=edgeHead[v]; edge[k].re=k - 1; edgeHead[v]=k ++; } bool spfa(int s,int t,int n){ //始点,终点,总点数 int i, head = 0, tail = 1; // 长注释的地方就是从最小费用改到最大费用时需要变动的地方 for(i = 0; i <= n; i ++){ dis[i] = -inf;//////////// vis[i] = false; } dis[s] = 0; que[0] = s; vis[s] = true; while(head != tail){ int u = que[head]; for(i = edgeHead[u]; i != 0; i = edge[i].next){ int v = edge[i].v; if(edge[i].cap && dis[v] <dis[u] + edge[i].cost){//////// dis[v] = dis[u] + edge[i].cost; pre[v] = i; if(!vis[v]){ vis[v] = true; que[tail ++] = v; if(tail == nMax) tail = 0; } } } vis[u] = false; head++; if(head ==nMax) head = 0; } if(dis[t] ==-inf) return false;/////////// return true; } void end(int s,int t){ int u, p; for(u = t;u!=s;u=edge[edge[p].re].v){ p = pre[u]; edge[p].cap-=1; edge[edge[p].re].cap+=1; ans+=edge[p].cost; } maxf+=1; //总流量 } int num[nMax]; char xxx[105][105]; int main(){ int n,m,i,j,s,t,a,b,c; while(scanf("%d",&n)!=EOF&&n){ k=1; ans=maxf=0; s=0,t=2*n+1; memset(edgeHead,0,sizeof(edgeHead)); for(i=1;i<=n;i++){ scanf("%d",&num[i]); } for(i=1;i<=n;i++) { scanf("%s",xxx[i]+1); } for(i=1;i<=n;i++) { addEdge(s,i,1,0); addEdge(i,t,1,0); /////!!!!!!! addEdge(i+n,t,1,0); } for(i=1;i<=n;i++) { for(j=1;j<=n;j++) { if(xxx[i][j]=='1') { a=num[i]^num[j]; addEdge(i,j+n,1,a); } } } while(spfa(s,t,2*n+2)){ end(s,t); } printf("%d\n",ans); } return 0; }
图片转自ac大神博客 Orz
发表评论
-
[kruskal]hdoj 4786
2014-10-29 20:38 666大致题意: 一个无向图中,每条边都是白边或 ... -
[prim]aizuoj:There is No Alternative
2014-10-20 01:02 850题目地址:http://judge.u-aizu.ac.j ... -
[最大流唯一性判断]hdoj 4888
2014-10-18 16:14 1320题意 给出一个矩阵n行每一行数字的和,m列每列数字的 ... -
[双连通分量+队列优化dijkstra]acdream 1415
2014-10-16 04:03 1102题意: 给出一个n个点,m条边无向图(2 ≤ ... -
[2-sat]hdoj 4751
2014-10-10 21:06 771大致题意 给出一个有向图,问这个图是否能分为两个完全图 ... -
[费用流]hdoj 5045
2014-09-28 00:11 835读题的时候漏掉了“题目是按照顺序出现的”,导致网络赛中这道题 ... -
[dfs+bfs]zoj 3811
2014-09-21 09:59 906题意: 在一个无向图中,能否按照一定的顺序访问图 ... -
[二分+最大流]zoj 3691:flower
2013-04-01 21:05 1613大致题意: 在一个三维空间中有n个点,每个点的坐标 ... -
[spfa]hdoj 4460:Friend Chains
2012-11-08 21:15 1604大致题意: 一个无向图n个点,m条边,求任意两个点之 ... -
[二分匹配]zoj 3156:Taxi
2012-10-25 19:28 1075大致题意: 有n个人和m辆车(n<=m)。给出所有 ... -
[Tarjan]uva 4846:Mines
2012-10-19 10:07 1227大致题意: 给出n个地雷,每颗地雷有一个爆炸范围,这 ... -
[2-sat][位运算]zoj 3656:Bit Magic
2012-10-15 09:17 1926大致题意: 给出下面一段代码 很明显这段代码是 ... -
[二分匹配]zoj 3646:Matrix Transformer
2012-10-10 21:15 981大致题意: 给出一个n*n的矩阵,每个矩阵元素的U或者 ... -
[拆点+网络流]2012 acm/icpc成都网络赛 hdoj 4292:Food
2012-09-16 17:15 2225大致题意: 有F种食物和D种饮料,每种食物或饮料只能 ... -
[网络流]2012 acm/icpc成都网络赛hdoj 4288:Control
2012-09-16 17:03 1308大致题意: 给出一个又n个点,m条边组成的无向图。给出两 ... -
[floyd+Tarjan]zoj 3232:It's not Floyd Algorithm
2012-09-09 09:49 1076大致题意: 给出一个有向图的传递闭包矩阵,求出这个图 ... -
[最大流]zoj 3642:Just Another Information Sharing Problem
2012-08-28 13:26 1102大致题意: 有n个人,每个人知道ai个消息,并且会 ... -
[Tarjan变形]zoj 3630:Information
2012-08-15 16:42 1107大致题意: 给出一个有向图,现在要删去一个点使得剩下的图 ... -
[Tarjan强连通分量]hdoj 3836:Equivalent Sets
2012-07-21 09:40 926大致题意: 就是给出一个有向图,求最少加多少条边可以 ... -
[最大流]zoj 3305:Get Sauce
2012-06-19 10:04 938大致题意: 有n种原材料,每种一件。现在给出m个组合 ...
相关推荐
HDOJ题目分类HDOJ题目分类HDOJ题目分类
ACM ICPC HDOJ1002
ACM ICPC HDOJ1001
hdoj1001标程
hdoj上的资源,代码有注释,很不错的哦
hdoj1004,解题代码,答案代码,欢迎下载
ACM ICPC HDOJ1008
ACM ICPC HDOJ1003
leetcode和hdoj 简介 主要用来记录算法刷题记录和一些模板 文件结构 leetcode 存放leetcode题目和周赛 atcoder 用于存放参与和vp的atcoder比赛 codeforces 用于存放参与和vp的cf比赛,比赛文件夹以比赛序号和div描述...
杭州电子科技大学hdoj1002,大整数相加问题
杭州电子科大HDOJ
ACM ICPC HDOJ1000
hdoj解题代码,题目为1000-1050
c语言 最短路 是hdoj上的一个最短路问题,写的很牛
Problem Description Calculate A + B. Input Each line will contain two integers A and B....HDOJ 代码: #include int main() { int a,b; while(scanf("%d %d",&a,&b)!=EOF) printf("%d\n",a+b); }
一些HDOJ上的DP题目的小总结,但愿能帮到那些想专攻DP的人吧
codj,hdoj的源码(50-60题)
包括简单数学 组合数学 动态规划 贪心算法 母函数 搜索算法 组合博弈论 计算几何 等等
kmp算法 KMP算法是一种用于在一个文本串S中查找一个模式串P出现位置的高效算法。KMP算法的核心思想是利用模式串P本身的信息来避免在文本串S中进行不必要的匹配。具体来说,KMP算法通过预处理模式串P,构建一个部分...
hdoj 2013 多校训练3标程+解题报告