HDU 3395 Special Fish(费用流)

题目地址:HDU 3395

刷了几道白书和CF上的非算法的智商题,感觉智商越来越接近负数了。。。还是先刷几道简单题缓缓。。

这题很简单,二分图模型,用费用流也可以,用KM也可以。不过需要注意的是这里是最大费用流,并不是最大费用最大流,区别在于是否是最大流,这题可以不是最大流,所以要当费用开始减少的时候停止继续流,来保证费用是最大的。

代码如下:

#include <iostream>
#include <cstdio>
#include <string>
#include <cstring>
#include <stdlib.h>
#include <math.h>
#include <ctype.h>
#include <queue>
#include <map>
#include <set>
#include <algorithm>

using namespace std;
const int INF=0x3f3f3f3f;
int head[200], source, sink, cnt, flow, cost, a[200];
int f[200], cur[200], d[200], vis[200];
char s[200][200];
struct node
{
    int u, v, cap, cost, next;
}edge[100000];
void add(int u, int v, int cap, int cost)
{
    edge[cnt].v=v;
    edge[cnt].cap=cap;
    edge[cnt].cost=cost;
    edge[cnt].next=head[u];
    head[u]=cnt++;

    edge[cnt].v=u;
    edge[cnt].cap=0;
    edge[cnt].cost=-cost;
    edge[cnt].next=head[v];
    head[v]=cnt++;
}
int spfa()
{
    int i;
    memset(d,INF,sizeof(d));
    memset(vis,0,sizeof(vis));
    cur[source]=-1;
    f[source]=INF;
    d[source]=0;
    queue<int>q;
    q.push(source);
    while(!q.empty())
    {
        int u=q.front();
        q.pop();
        vis[u]=0;
        for(i=head[u];i!=-1;i=edge[i].next)
        {
            int v=edge[i].v;
            if(d[v]>d[u]+edge[i].cost&&edge[i].cap)
            {
                d[v]=d[u]+edge[i].cost;
                f[v]=min(f[u],edge[i].cap);
                cur[v]=i;
                if(!vis[v])
                {
                    vis[v]=1;
                    q.push(v);
                }
            }
        }
    }
    if(d[sink]==INF) return 0;
    if(d[sink]>=0) return 0;
    flow+=f[sink];
    cost+=f[sink]*d[sink];
    for(i=cur[sink];i!=-1;i=cur[edge[i^1].v])
    {
        edge[i].cap-=f[sink];
        edge[i^1].cap+=f[sink];
    }
    return 1;
}
void mcmf()
{
    cost=flow=0;
    while(spfa()) ;
    printf("%d\n",-cost);
}
int main()
{
    int n, i, j;
    while(scanf("%d",&n)!=EOF&&n)
    {
        memset(head,-1,sizeof(head));
        cnt=0;
        source=0;
        sink=2*n+1;
        for(i=1;i<=n;i++)
        {
            scanf("%d",&a[i]);
        }
        for(i=1;i<=n;i++)
        {
            scanf("%s",s[i]);
            add(source,i,1,0);
            //add(i,sink,1,0);
            for(j=0;j<n;j++)
            {
                if(s[i][j]=='1')
                {
                    add(i,j+n+1,1,-(a[i]^a[j+1]));
                }
            }
        }
        for(i=1;i<=n;i++)
        {
            add(i+n,sink,1,0);
        }
        mcmf();
    }
    return 0;
}
时间: 2024-10-29 19:08:07

HDU 3395 Special Fish(费用流)的相关文章

HDU 3395 Special Fish 最“大”费用最大流

求最大费用可以将边权取负以转化成求最小费用.然而此时依然不对,因为会优先寻找最大流,但是答案并不一定出现在满流的时候.所以要加一些边(下图中的红边)使其在答案出现时满流.设所有边的流量为1,花费如下图所示.显然最大花费是1001,而没有红边的情况下会得到3. #include <algorithm> #include <iostream> #include <cstring> #include <cstdlib> #include <cstdio>

HDU 3395 Special Fish(拆点+最大费用最大流)

Special Fish Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 2367    Accepted Submission(s): 878 Problem Description There is a kind of special fish in the East Lake where is closed to campus o

HDU 3395 Special Fish(最大费用流)

Special Fish Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 1814    Accepted Submission(s): 678 Problem Description There is a kind of special fish in the East Lake where is closed to campus o

[ACM] HDU 3395 Special Fish (二分图最大权匹配,KM算法)

Special Fish Problem Description There is a kind of special fish in the East Lake where is closed to campus of Wuhan University. It's hard to say which gender of those fish are, because every fish believes itself as a male, and it may attack one of s

HDU 3395 Special Fish【最大权匹配】

题意:最大权匹配 分析:最大全匹配 代码: 1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 using namespace std; 5 6 const int maxn = 105; 7 const int INF = 2000000000; 8 9 bool Sx[maxn], Sy[maxn]; 10 int Lx[maxn], Ly[maxn]; 11 int Link[maxn]

POJ 2135 Farm Tour &amp;&amp; HDU 2686 Matrix &amp;&amp; HDU 3376 Matrix Again 费用流求来回最短路

累了就要写题解,最近总是被虐到没脾气. 来回最短路问题貌似也可以用DP来搞,不过拿费用流还是很方便的. 可以转化成求满流为2 的最小花费.一般做法为拆点,对于 i 拆为2*i 和 2*i+1,然后连一条流量为1(花费根据题意来定) 的边来控制每个点只能通过一次. 额外添加source和sink来控制满流为2. 代码都雷同,以HDU3376为例. #include <algorithm> #include <iostream> #include <cstring> #in

HDU 4067 Random Maze 费用流

Random Maze Time Limit: 10000/3000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 1114    Accepted Submission(s): 387 Problem Description In the game "A Chinese Ghost Story", there are many random mazes which h

hdu 3315 My Brute 费用流,费用最小且代价最小

很常见的想法了= = #include <stdio.h> #include <iostream> #include <string.h> using namespace std; const int N=400; const int MAXE=200000; const int inf=1<<30; int head[N],s,t,cnt,n,m,ans; int d[N],pre[N]; bool vis[N]; int q[MAXE]; int V[N

hdoj 3395 Special Fish 【最大费用流】

Special Fish Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 1920    Accepted Submission(s): 717 Problem Description There is a kind of special fish in the East Lake where is closed to campus o