• POJ3041:Asteroids——题解


    http://poj.org/problem?id=3041

    题目大意:激光可以干掉一整行或一整列陨石,求最少激光次数。

    ——————————————————

    二分图匹配,对于每一个陨石将它的横纵坐标相连。

    然后发现我们需要将每一条边中的端点之一都覆盖掉,就是最小点覆盖。

    有结论最小点覆盖=最大匹配数。

    然后本题就切了。

    #include <cstdio>
    #include <iostream>
    #include <cmath>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    const int M=10010;
    const int N=1010;
    const int INF=2147483640;
    inline int read(){
        int X=0,w=0;char ch=0;
        while(ch<'0'||ch>'9'){w|=ch=='-';ch=getchar();}
        while(ch>='0'&&ch<='9')X=(X<<3)+(X<<1)+(ch^48),ch=getchar();
        return w?-X:X;
    }
    struct node{
        int next;
        int to;
        int w;
    }edge[N*2+M*2];
    int head[N],cnt=-1;
    void add(int u,int v,int w){//u起点v终点w容量 
        cnt++;
        edge[cnt].to=v;
        edge[cnt].w=w;
        edge[cnt].next=head[u];
        head[u]=cnt;
        return;
    }
    int lev[N],cur[N];//lev层数,cur[i]为以i为起点的边的编号 
    bool bfs(int m){//强制1为源点,m为汇点 
        int dui[m],r=0;//队列和右指针 
        for(int i=1;i<=m;i++){//初始化 
            lev[i]=-1;
            cur[i]=head[i];
        }
        dui[0]=1,lev[1]=0;
        int u,v;//u起点v终点 
        for(int l=0;l<=r;l++){//左指针 
            u=dui[l];
            for(int e=head[u];e!=-1;e=edge[e].next){
                v=edge[e].to;
                if(edge[e].w>0&&lev[v]==-1){//1.能走 2.未分层 
                    lev[v]=lev[u]+1;
                    r++;
                    dui[r]=v;//v入队 
                    if(v==m)return 1;//分层完毕 
                }
            }
        }
        return 0;//无法分层 
    }
    int dinic(int u,int flow,int m){//u当前点,flow为下面的点能够分配多大的流量,m终点 
        if(u==m)return flow;//终点直接全流入
        int res=0,delta;//res实际流量 
        for(int &e=cur[u];e!=-1;e=edge[e].next){//'&'相当于cur[u]=e;即流满的边不会再被扫一次 
            int v=edge[e].to;
            if(edge[e].w>0&&lev[u]<lev[v]){//只能从低层往高层流 
                delta=dinic(v,min(edge[e].w,flow-res),m); 
                if(delta>0){//如果增广 
                    edge[e].w-=delta;//正向边容量减少 
                    edge[e^1].w+=delta;//反向边仍量增加(暗示退流) 
                    res+=delta;//扩张流量增加 
                    if(res==flow)break;//可流的都流完了,及时跳出 
                }
            }
        }
        if(res!=flow)lev[u]=-1;//没流完,说明以后不能从这个点流出任何流量,那就不需要这个点了 
        return res;
    }
    int main(){
        int n=read();
        int k=read();
        int m=n*2+2;
        memset(head,-1,sizeof(head));
        for(int i=1;i<=k;i++){
        int s=read()+1;
        int e=read()+n+1;
        add(s,e,1);
        add(e,s,0);
        }
        for(int i=1;i<=n;i++){
        add(1,i+1,1);
        add(i+1,1,0);
        add(i+n+1,m,1);
        add(m,i+n+1,0);
        }
        int ans=0;
        while(bfs(m)==1)ans+=dinic(1,INF,m);
        printf("%d
    ",ans);
        return 0;
    }
  • 相关阅读:
    @Autowired 注解是如何实现的?
    工作 3 年的同事不懂 isEmpty 和 isBlank 的区别,我真是醉了。。
    4 个单词,谷歌返回 16 个 SQL 注入漏洞...
    MySQL 更新不成功,事务问题搞清楚了吗?
    Python Web应用如何部署?
    mapbox加载postgis矢量切片
    tile2lon:地图瓦片编号与经纬度的换算关系
    shp2pgsql:将shapefile导入postgis数据库
    postgreSQL表添加ID自增列
    postgreSQL连接配置
  • 原文地址:https://www.cnblogs.com/luyouqi233/p/7930680.html
Copyright © 2020-2023  润新知