zoukankan      html  css  js  c++  java
  • UVa11419

    题目链接

    简介:
    子弹打小怪,一发打一行(列),求最小花费的子弹数,并给出方案

    分析:
    曾经做过和这个有一点相似的题(我又开始考古啦
    然而这道题要简单一点,
    还是把每一行,每一列看作是一个点,
    如果(i,j)位置上有小怪物,那我们就连接Xi—>Yj,流量是INF
    源点向横向点集(X)连边,流量为1
    纵向点集(Y)向汇点连边,流量是1

    为什么这样建图是对的呢:
    我们可以把每一条连接X和Y的边看做是小怪物
    用最小割的思维,这些边我们都是不会割掉的
    所以我们每次只会选择源点和X,Y和汇点之间的连边割掉
    这样就可以轻松地得到最小子弹数

    但是难点在如何构造合法方案
    直接判断是否有流量是不行的

    这道题的正解是二分图最大匹配,方案的求解需要匈牙利树
    我这是真没招了
    看一下dalao的正解

    附上第一问的网络流解法

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<queue>
    
    using namespace std;
    
    const int INF=0x33333333;
    const int N=1002;
    struct node{
        int x,y,v,nxt;
    };
    node way[N*N*2];
    int s,t,st[N*2],tot,deep[N],cur[N],n,m,x;
    
    void add(int u,int w,int z)
    {
        tot++;
        way[tot].x=u;way[tot].y=w;way[tot].v=z;way[tot].nxt=st[u];st[u]=tot;
        tot++;
        way[tot].x=w;way[tot].y=u;way[tot].v=0;way[tot].nxt=st[w];st[w]=tot;
    }
    
    int bfs(int s,int t)
    {
        for (int i=s;i<=t;i++) cur[i]=st[i];
        memset(deep,-1,sizeof(deep));
        deep[s]=1;
        queue<int> Q;
        Q.push(s);
    
        while (!Q.empty())
        {
            int now=Q.front(); Q.pop();
            for (int i=st[now];i!=-1;i=way[i].nxt)
                if (way[i].v&&deep[way[i].y]==-1)
                {
                    deep[way[i].y]=deep[now]+1;
                    Q.push(way[i].y);
                }
        }
    
        return deep[t]!=-1; 
    }
    
    int dfs(int now,int t,int limit)
    {
        if (!limit||now==t) return limit;
        int f,flow=0;
        for (int i=cur[now];i!=-1;i=way[i].nxt)
        {
            cur[now]=i;
            if (way[i].v&&deep[way[i].y]==deep[now]+1&&(f=dfs(way[i].y,t,min(limit,way[i].v))))
            {
                flow+=f;
                limit-=f;
                way[i].v-=f;
                way[i^1].v+=f;
                if (!limit) break;
            }
        }
        return flow;
    }
    
    int dinic(int s,int t)
    {
        int ans=0;
        while (bfs(s,t))
            ans+=dfs(s,t,INF);
        return ans;
    }
    
    int main()
    {
        int cnt=0;
        while (scanf("%d%d%d",&n,&m,&x)!=EOF&&n)
        {
            memset(st,-1,sizeof(st));
            tot=-1;
            s=0; t=n+m+1;
            for (int i=1;i<=x;i++)
            {
                int u,w;
                scanf("%d%d",&u,&w);
                add(u,w+n,INF);
            }
            for (int i=1;i<=n;i++) add(s,i,1);
            for (int i=1;i<=m;i++) add(i+n,t,1);
    
            int ans=dinic(s,t);
            printf("%d
    ",ans);
        }
        return 0;
    }
  • 相关阅读:
    StrCopy、StrCat、StrPas
    WinAPI: FlashWindow 闪烁窗口
    WinAPI: SetVolumeLabel 设置磁盘卷标
    WinAPI: GetActiveWindow 获取当前活动窗口的句柄
    WinAPI: SetCurrentDirectory、GetCurrentDirectory 设置与获取当前目录
    WinAPI: CreateDirectoryEx 根据模版建立文件夹
    WinAPI: CreateDirectory 建立文件夹
    WinAPI: RemoveDirectory 删除空目录
    WinAPI: GetLogicalDriveStrings 获取系统中存在的逻辑驱动器字符串
    filer.js: 一个 Unix 命令风格的 HTML 5 FileSystem API 封装 V2EX
  • 原文地址:https://www.cnblogs.com/wutongtong3117/p/7673000.html
Copyright © 2011-2022 走看看