• POJ 1087 A Plug for UNIX 【最大流】


    这道题的建模不太难,基本你用过转换插头的话就明白是怎么回事了hh

    1.源点与所有【已有plug】连边

    2.【所有device】与汇点连边

    3.该device用的插头与device连边

    4.转换插头连边,这里容量是INF

    网络流里流的是这种安排plug的方案可不可行,1是可行,0是不可行

    做题的时候我偷了个懒,因为用了离散化,我想在最后的转接插头的时候,读进来A B,如果A插头之前没出现过,那就算B换过来也用不了;如果B之前没出现过,那根本没法换。所以我加了一行代码

    if( plug_name[to]==0 || plug_name[from]==0 ) continue;

    就是这行代码让我wa了好久。

    这么贪心是不对的,因为可能A和0插头出现过,然后转换插头是1 0,2 1,3 2,A 3,所以就错了

     

    #include<iostream>
    #include<deque>
    #include<vector>
    #include<cstring>
    #include<string>
    #include<map>
    #include<stdio.h>
    #define INF 2e9
    using namespace std;
    
    int T=1000;
    
    struct edge{
        int v,cap,reverse;
    };
    vector<int> edges[1005];//邻接表 
    vector<edge> bian;//所有的边都存在里面 
    
    void addedge(int u,int v,int cap){//u到v一条边,再加一条反向边 
        edge e;
        e.cap=cap;
        e.v=v;
        e.reverse=bian.size()+1;//这条边的反边将建在这条边之后(这条边建完后在bian.size()的位置) 
        bian.push_back(e);
        edges[u].push_back(bian.size()-1);
        
        e.cap=0;
        e.v=u;
        e.reverse=bian.size()-1;
        bian.push_back(e);
        edges[v].push_back(bian.size()-1);
    }
    
    int layer[1005],vis[1005];
    bool count_layer(){
        memset(layer,0,sizeof(layer));
        deque<int> q;
        layer[0]=1; q.push_back(0);
        while( !q.empty() ){
            int u = q.front(); q.pop_front();
            if( u==T ) return true;
            for(int i=0;i<edges[u].size();i++){//所有以u为起点的边的边的索引 
                edge &e = bian[ edges[u][i] ];
                int v=e.v;
                if( !layer[v] && e.cap>0 ){
                    layer[v] = layer[u] + 1;
                    q.push_back( v );
                }
            }
        }
        return false;
    }
    
    int dinic(){
        int max_flow=0;
        while( count_layer() ){
            memset(vis,0,sizeof(vis));
            deque<int> q,path;//记录一路走过来的【点】和【边的索引】 
            q.push_back(0); vis[0]=1;
            while(!q.empty()){
                int u = q.back();
                if( u==T ){
                    int min_u,min_v,min_flow=INF;
                    int p=0;//从0点出发 
                    for(int i=0;i<path.size();i++){
                        edge &e = bian[ path[i] ];
                        if( e.cap<min_flow ){
                            min_u=p;
                            min_flow=e.cap;
                        }
                        p=e.v;
                    }
                    
                    p=0;
                    max_flow+=min_flow;
                    for(int i=0;i<path.size();i++){
                        edge &e = bian[ path[i] ];
                        e.cap-=min_flow;
                        bian[e.reverse].cap+=min_flow;
                    }
                    //回溯
                    while( !q.empty() && q.back()!=min_u ){
                        vis[ q.back() ]=0;
                        q.pop_back();
                        path.pop_back();
                    } 
                }
                else{//T边 
                    int i;
                    for(i=0;i<edges[u].size();i++){
                        edge &e = bian[ edges[u][i] ];
                        if( layer[e.v]==layer[u]+1 && !vis[e.v] && e.cap>0 ){
                            vis[e.v]=1;
                            q.push_back( e.v );
                            path.push_back( edges[u][i] );
                            break;
                        }
                    }
                    if(i==edges[u].size()) {
                        q.pop_back();
                        path.pop_back();
                    }
                }        
                
            }
        }
        return max_flow;
    }
    
    int id;
    map<string,int> plug_name;//避免同样的插头有多个节点 
    
    int main(){
        int n,m,k;        
            cin>>n;
            //所有已有plug  
            for(int i=1;i<=n;i++){ 
                string name; cin>>name;
                plug_name[ name ] = ++id;
                addedge(0,id,1);//从源点到每个原有的plug连一个条边 
            }
        
            cin>>m;//所有device
            for(int i=1;i<=m;i++){
                string name,type; cin>>name>>type;
                id++;
                addedge(id,T,1);//device到汇点建一条边 ,设汇点在1000
                if( plug_name[type]==0 ){//之前没出现过这个插座 
                    plug_name[type]= ++id;
                    addedge(id,id-1,1);//插座到device
                }
                else addedge( plug_name[type],id,1 );
            }
        
            cin>>k;//所有转接插头
            for(int i=1;i<=k;i++){
                string to,from; cin>>to>>from;
                if( plug_name[to]==0 ) plug_name[to]= ++id;
                if( plug_name[from]==0 ) plug_name[from]= ++id;
                //if( plug_name[to]==0 || plug_name[from]==0 ) continue;
            
                addedge(plug_name[from],plug_name[to],INF);
            } 
     
            cout<<m-dinic();
        
        
        return 0;    
    }
  • 相关阅读:
    测试用例编写(功能测试框架)
    OKR与KPI管理的区别与联系
    手机测试常见的BUG解析
    软件测试之BUG分析定位概述(QA如何分析定位BUG)【转自 https://blog.csdn.net/kaka1121/article/details/51538979】
    KPI、KPA、OKR三者的区别
    swagger api 文档框架
    Jmeter + Ant + Jenkins 接口/性能测试,持续集成环境搭建
    重建词汇精神家园
    记忆的本质
    attention机制七搞八搞
  • 原文地址:https://www.cnblogs.com/ZhenghangHu/p/9522641.html
Copyright © 2020-2023  润新知