HDU 3395 Special Fish?费用流(虚拟边)?647★KM(加虚拟边权)
来源:互联网 发布:网络小说家排名 编辑:程序博客网 时间:2024/05/16 08:17
题意:给定二分图,求权值最大的匹配,
思路:1.KM,因为题目给定的图不是完全图,可能没有完全匹配,所以要加上虚拟的权值为0的边,
所有情况,包括权值最大的情况也是属于某一完全匹配的,所以可以直接求KM,
2.费用流:不加虚拟边,求得的是在最大流情况下的权值最大,
加上虚拟边后,所有情况,包括最大权值情况都是属于某一最大流,所以直接求费用流
费用流:
#include<cstdio>#include<iostream>#include<cstring>#include<queue>#include<cmath>using namespace std;const int N=200+10;const int M=200000+10;const int INF=1<<30;inline int min(int a,int b){ return a<b?a:b;}struct Edge{ int from,to,next,cap,cost;}e[M];int head[N];int in(){ int res = 0 , ch ; while( !( ( ch = getchar() ) >= '0' && ch <= '9' ) ); res = ch - '0' ; while( ( ch = getchar() ) >= '0' && ch <= '9' ) res = res * 10 + ( ch - '0' ) ; return res ;}struct Mcmf{ int total; int dis[N],vis[N]; int path[N],low[N]; void init() { total=0; memset(head,-1,sizeof(head)); } void add_edges(int from,int to,int cap,int cost) { e[total].from=from; e[total].cap=cap; e[total].to=to; e[total].cost=cost; e[total].next=head[from]; head[from]=total++; e[total].from=to; e[total].cap=0; e[total].to=from; e[total].cost=-cost; e[total].next=head[to]; head[to]=total++; } int Spfa(int s,int t) { memset(vis,0,sizeof(vis)); memset(path,-1,sizeof(path)); memset(dis,0x6f,sizeof(dis)); queue<int > qq; qq.push(s); vis[s]=1; dis[s]=0; while(!qq.empty()) { //printf("ans\n"); int u=qq.front();qq.pop(); vis[u]=0; for(int i=head[u];i!=-1;i=e[i].next) { int v=e[i].to; if(e[i].cap>0&&(dis[v]>dis[u]+e[i].cost)) { path[v]=i; dis[v]=dis[u]+e[i].cost; if(!vis[v]) { vis[v]=1; qq.push(v); } } } }///////////while if(path[t]==-1)return 0; return 1; } int _mcmf(int s,int t) { int flow=0; int cost=0; while(Spfa(s,t)) { int f=INF; for(int i=t;i!=s;i=e[path[i]].from) { //printf("%d-",i); f=min(f,e[path[i]].cap); } //printf("\n"); for(int i=t;i!=s;i=e[path[i]].from) { e[path[i]].cap-=f; e[path[i]^1].cap+=f; } flow+=f; cost+=dis[t]; } //printf("flow=%d\n",flow); return cost; }}mcmf;int aa[150];char str[150];int main(){ int n; while(scanf("%d",&n),n) { mcmf.init(); for(int i=1;i<=n;i++) { scanf("%d",&aa[i]); mcmf.add_edges(0,i,1,0); mcmf.add_edges(i+n,2*n+1,1,0); } for(int i=1;i<=n;i++) { scanf("%s",str); for(int j=0;j<n;j++) { if(str[j]=='1') { mcmf.add_edges(i,j+1+n,1,-(aa[i]^aa[j+1])); //printf("%d,",aa[i]^aa[j+1]); } else mcmf.add_edges(i,j+1+n,1,0); } //printf("\n"); } int ans=mcmf._mcmf(0,2*n+1); printf("%d\n",-ans); } return 0;}
0 0
- HDU 3395 Special Fish?费用流(虚拟边)?647★KM(加虚拟边权)
- 【HDU】 3395 Special Fish 费用流(可KM匹配)
- hdu 3395 Special Fish(费用流//KM匹配)
- HDU 3395 Special Fish(KM)
- hdu 3395 Special Fish(费用流)
- HDU 3395 Special Fish | 费用流
- HDU 3395 Special Fish(费用流)
- HDU 3395 Special Fish 费用流
- HDU 3395 Special Fish(最大费用流)
- hdu 3395 Special Fish 最大费用流
- hdu 3395 Special Fish【最大费用流】
- hdu 3395 Special Fish 带权匹配 费用流
- HDU 3395 Special Fish KM水题
- HDU 3395 Special Fish(KM算法)
- HDU 3395Special Fish 最“大”费用最大流
- hdu 3395 Special Fish(异或,最大费用任意流,最优匹配)
- hdoj 3395 Special Fish 【最大费用流】
- hdu3395 Special Fish(KM)
- Velocity 语法(转)
- Ubuntu 14.04中文输入法的安装
- 迷宫问题
- Unicode字符集和多字节字符集关系
- spring+静态代理
- HDU 3395 Special Fish?费用流(虚拟边)?647★KM(加虚拟边权)
- Go语言之nil详解
- IDF实验室之万里寻踪图片里的秘密
- leetcode database 题目
- Android 异步加载图片,使用LruCache和SD卡或手机缓存,效果非常的流畅
- STL源码剖析—整体简要概述
- AsynImageLoader andriod异步加载图片类
- Vector Clock算法的理解
- database link